Ghost Theme yarn zip Command Fails: How to Fix TypeError zip is not a function

Ghost theme yarn zip command fails - TypeError zip is not a function fix

Quick answer: The yarn zip command in Ghost theme development fails with TypeError: zip is not a function when your installed gulp-zip version is incompatible with your Gulp version. Fix it by running yarn add gulp-zip@5.1.0 --dev to pin to the last stable v5 release. If you're on Gulp 5 (Casper/Source themes), upgrade to gulp-zip@6.1.0 instead.

Ghost theme yarn zip command fails - TypeError zip is not a function fix

You spent the afternoon customizing your Ghost theme. The CSS tweaks look good locally, you run yarn zip to package it up, and you get:

yarn run v1.22.22
$ gulp zip
[09:32:16] Starting 'zip'...
[09:32:16] Starting 'css'...
[09:32:16] Finished 'css' after 198 ms
[09:32:16] Starting 'zipper'...
[09:32:16] 'zipper' errored after 1.06 ms
[09:32:16] TypeError: zip is not a function

That error has burned countless Ghost developers. It shows up when the gulp-zip package in your node_modules is the wrong version for the Gulp major release your theme uses. The fix is usually a single command — but understanding why it breaks helps you avoid it next time.

Why does yarn zip fail with "TypeError: zip is not a function"?

Ghost themes like Source and Casper use Gulp and Yarn to compile CSS and bundle assets. The yarn zip script maps to gulp zip, which calls a zipper task in the theme's gulpfile.js. That task uses the gulp-zip plugin to produce a .zip file you can upload to Ghost Admin.

Here's the problem: gulp-zip had a breaking API change between v5 and v6. Version 5 exports a default function, so you call zip('filename.zip'). Version 6 changed to a named export. If you cloned an older theme starter or ran yarn install on a project where the lockfile was out of date, you can end up with a mismatched gulp-zip.

gulp-zip versionGulp compatibilityImport style
v5.xGulp 4Default export: const zip = require('gulp-zip')
v6.xGulp 5+Named export: const { zip } = require('gulp-zip')

If your theme's gulpfile.js uses const zip = require('gulp-zip') but gulp-zip@6 is installed, the variable zip becomes an object instead of a function. When the task calls zip('theme.zip'), Node throws TypeError: zip is not a function.

How do I fix the "zip is not a function" error?

The quickest fix — confirmed in the Ghost forum thread — is to pin gulp-zip to the v5 line:

yarn add gulp-zip@5.1.0 --dev

This downgrades gulp-zip to match the Gulp 4 API your theme's gulpfile.js expects. After the install finishes, run yarn zip again and the task should complete cleanly.

If that still doesn't work, try clearing your cache first:

rm -rf node_modules
yarn cache clean
yarn install
yarn add gulp-zip@5.1.0 --dev
yarn zip

What if I'm using the latest Casper or Source theme?

Ghost's official themes — Casper and Source — switched to Gulp 5 in 2024. If you cloned a recent version of either theme from GitHub, they already use gulp-zip@6.1.0 and the newer named import. In that case, you want the latest package, not the pinned v5:

yarn add gulp-zip@latest --dev

To check which Gulp version your theme is actually using:

cat node_modules/gulp/package.json | grep '"version"'

Gulp 4 → use gulp-zip@5.1.0. Gulp 5 → use gulp-zip@6.1.0 or @latest.

What does the "engine ghost appears to be invalid" warning mean?

Alongside the zip error, you might see:

warning source-dnn@1.0: The engine "ghost" appears to be invalid.

This is harmless. Ghost themes can declare an engines.ghost field in package.json to specify the minimum Ghost version they need. Yarn doesn't know about the "ghost" engine (it only understands "node" and "npm"), so it flags the field as invalid. The build still runs fine. You can ignore this warning entirely.

Are there other reasons yarn zip might fail?

Yes, a few. Here's a quick breakdown:

Error messageCauseFix
TypeError: zip is not a functiongulp-zip version mismatchyarn add gulp-zip@5.1.0 --dev
Error: spawn gulp ENOENTGulp not installed or not in PATHyarn add gulp --dev or npx gulp zip
The engine "node" is incompatibleNode version too old or too newSwitch Node with nvm use 18
Cannot find module 'gulp/gulpfile.js'Incomplete yarn installDelete node_modules and reinstall
Task function must be specifiedgulpfile written for Gulp 3 syntaxUpdate to Gulp 4+ task syntax

The most common one outside the zip issue is a Node version problem. Ghost CMS itself requires Node v22 LTS as of 2026. Theme development tools like Gulp generally work fine on Node 18 through 22, but some older theme starters might have issues on v22. Use nvm to manage Node versions for Ghost projects.

How do I package a Ghost theme without Yarn or Gulp?

If you don't need to compile Sass or PostCSS — for example, you're only editing HTML templates and plain CSS — you can skip the build tools entirely and zip the theme manually.

On macOS/Linux:

# From inside your theme directory
cd /path/to/your-theme
zip -r your-theme.zip . --exclude "*.DS_Store" --exclude "node_modules/*" --exclude ".git/*"

On Windows (PowerShell):

Compress-Archive -Path .\* -DestinationPath .\your-theme.zip -Exclude "node_modules", ".git"

The result is a .zip you can upload directly in Ghost Admin under Settings → Design → Change theme → Upload theme.

One thing to watch: do not include node_modules in your zip. Ghost will reject the upload if it detects node_modules inside the archive, because some modules like gscan contain symlinks that break Ghost's zip parser.

How does yarn zip actually work under the hood?

In most Ghost themes, yarn zip is just an alias for gulp zip, defined in package.json scripts:

"scripts": {
  "dev": "gulp",
  "zip": "gulp zip",
  "test": "gscan ."
}

The gulpfile.js in the theme root defines what gulp zip does. Typically it:

  1. Compiles CSS (PostCSS + autoprefixer)
  2. Minifies JavaScript
  3. Copies locale files
  4. Creates a .zip archive in the dist/ folder

The output file (e.g. dist/casper.zip) is what you upload to Ghost. After uploading, Ghost activates the theme and you can activate it from the Design settings.

For faster iteration, skip the zip step during development. Run yarn dev instead — it watches your files and recompiles on save. You only need yarn zip when you're ready to push changes to your live site.

How do I set up Ghost theme development from scratch?

If you're starting fresh, here's the minimal setup that avoids most yarn/gulp pain:

# 1. Install Node v22 LTS (recommended for Ghost in 2026)
nvm install 22
nvm use 22

# 2. Clone a theme (Casper or Source as starting point)
git clone https://github.com/TryGhost/Casper.git my-theme
cd my-theme

# 3. Install dependencies
yarn install

# 4. Start local dev (watches files, recompiles CSS)
yarn dev

# 5. When ready to deploy, build the zip
yarn zip
# Output: dist/casper.zip

You'll also want a local Ghost install running at the same time so you can preview changes without uploading. The standard approach is Ghost CLI in local mode:

ghost install local --dir my-ghost-site
cd my-ghost-site
ghost start

Then symlink your theme folder into content/themes/ or use the full Yarn + Gulp live-reload setup to see changes in the browser without restarting Ghost. Once yarn dev is running, CSS updates show up automatically — no restart needed, as long as you disable browser caching in DevTools.

Does Ghost have an official way to validate a theme before uploading?

Yes. Ghost ships a tool called gscan that checks your theme for errors and compatibility issues before you upload it. It's usually already in your devDependencies:

# Run from your theme directory
yarn test
# or directly:
npx gscan .

gscan flags missing required template files, unsupported helpers, and package.json errors that would cause Ghost to reject the upload. Running it before yarn zip saves you the frustrating cycle of uploading a broken theme to find out something is wrong.

The output shows warnings (won't block upload) and errors (will block upload). Fix errors first. For most customized themes based on Casper or Source, the only things that trigger errors are missing the index.hbs file or removing required partials. Keep those in place even if you don't use them.

Frequently Asked Questions

Why does yarn zip say "zip is not a function" in Ghost themes?

This happens because gulp-zip changed its export style between v5 (default export) and v6 (named export). If your theme's gulpfile.js imports it the old way but has gulp-zip@6 installed, the function call fails. Run yarn add gulp-zip@5.1.0 --dev to fix it.

What version of gulp-zip should I use for Ghost theme development?

It depends on your Gulp version. If your theme uses Gulp 4 (most older themes and custom starters), use gulp-zip@5.1.0. If you're on Gulp 5 (latest Casper and Source), use gulp-zip@6.1.0.

How do I know which version of Gulp my Ghost theme uses?

Check package.json in the theme root. Look for "gulp" in devDependencies. Version 4.x means Gulp 4; version 5.x means Gulp 5. Or run cat node_modules/gulp/package.json | grep '"version"'.

Can I zip a Ghost theme without using yarn or gulp?

Yes. For themes without compiled assets, just zip the folder manually: zip -r theme.zip . --exclude "node_modules/*". Make sure node_modules is excluded — Ghost rejects uploads containing it.

Why does Ghost reject my theme zip upload?

Three common reasons: the zip includes node_modules, the zip was created from a parent folder instead of inside the theme directory (wrong folder structure), or the theme is missing required files like index.hbs. Run yarn test (gscan) before uploading to catch most issues.

What does "The engine ghost appears to be invalid" mean in yarn?

It's just a warning, not an error. Ghost theme packages can declare a custom engines.ghost field, but Yarn doesn't recognize it. The build still works. Ignore this message.

Does yarn zip work on Windows for Ghost themes?

Yes, with the right setup. You need Node and Yarn installed on Windows (or via WSL2). The most common Windows-specific issue is path separators in the Gulpfile. If you get errors on Windows that don't appear on Mac/Linux, try running in WSL2 — it eliminates most cross-platform build issues.

How do I prevent yarn zip from failing after updating Node?

After a Node version change, always delete node_modules and reinstall: rm -rf node_modules && yarn install. Native modules compiled against the old Node version won't work. If you upgrade from Node 18 to Node 22, this step is non-optional.

The simplest path forward: check your Gulp version first, then match your gulp-zip version to it. Running yarn add gulp-zip@5.1.0 --dev fixes the error for the vast majority of Ghost theme developers. If you're starting a new theme from the official Casper or Source repo in 2026, pull the latest version — it already ships with the correct gulp-zip version and you shouldn't hit this issue at all.

Subscribe to Ghost SEO

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe