TryGhost/Ghost · warning · ThemeArchiveExtractionError
too_many_files
too_many_files
Error message
This theme archive contains too many files for the browser editor (${entries.length}/${THEME_EDITOR_ARCHIVE_LIMITS.maxFiles}). What it means
Thrown by assertThemeArchiveLimits in theme-editor-utils when a uploaded theme .zip contains more than THEME_EDITOR_ARCHIVE_LIMITS.maxFiles (1000) non-directory entries. It is a browser-side guard: the in-browser theme editor (JSZip-based) is not designed to ingest huge archives (e.g. ones accidentally bundling node_modules or generated asset variants), so extraction is aborted before memory/time becomes a problem. Thrown as ThemeArchiveExtractionError with reason 'too_many_files'.
Source
Thrown at apps/admin/src/settings/app/components/settings/site/theme/theme-editor-utils.ts:189
return `${megabytes.toFixed(1)} MB`;
};
const collectArchiveEntries = (zip: JSZip) => {
const entries: Array<[string, JSZip.JSZipObject]> = [];
zip.forEach((relativePath, entry) => {
if (!entry.dir) {
entries.push([relativePath, entry]);
}
});
return entries;
};
const assertThemeArchiveLimits = (entries: Array<[string, JSZip.JSZipObject]>) => {
if (entries.length > THEME_EDITOR_ARCHIVE_LIMITS.maxFiles) {
throw new ThemeArchiveExtractionError(
'too_many_files',
`This theme archive contains too many files for the browser editor (${entries.length}/${THEME_EDITOR_ARCHIVE_LIMITS.maxFiles}).`
);
}
};
const loadThemeArchive = async (arrayBuffer: ArrayBuffer) => {
try {
return await JSZip.loadAsync(arrayBuffer);
} catch {
throw new ThemeArchiveExtractionError('invalid_archive', invalidArchiveMessage);
}
};
const readThemeBinaryFile = async (entry: JSZip.JSZipObject) => {
try {
return await entry.async('uint8array');
} catch {View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Re-zip the theme excluding node_modules, .git, and large generated asset directories so it contains only the theme files Ghost needs.
- Verify the file count locally before upload: unzip -l theme.zip | tail -1 (or JSZip inspection) to confirm it's under 1000 entries.
- If the limit is genuinely too low for a legitimate theme, raise THEME_EDITOR_ARCHIVE_LIMITS.maxFiles in code, but treat that as a last resort — the browser editor isn't meant for arbitrarily large archives.
- Prefer uploading the theme via the Ghost Admin upload (server-side extraction) instead of the in-browser editor for large themes.
Example fix
// before — extraction throws ThemeArchiveExtractionError mid-flow
const snapshot = await extractThemeArchive(arrayBuffer);
// after — catch and branch on the typed reason
import {ThemeArchiveExtractionError} from './theme-editor-utils';
try {
const snapshot = await extractThemeArchive(arrayBuffer);
} catch (e) {
if (e instanceof ThemeArchiveExtractionError && e.reason === 'too_many_files') {
setUploadError(e.message); // 'This theme archive contains too many files ...'
return;
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
import {ThemeArchiveExtractionError} from './theme-editor-utils';
function isTooManyFiles(e: unknown): e is ThemeArchiveExtractionError {
return e instanceof ThemeArchiveExtractionError && e.reason === 'too_many_files';
} Try / catch
import {extractThemeArchive, ThemeArchiveExtractionError} from './theme-editor-utils';
try {
const snapshot = await extractThemeArchive(arrayBuffer);
} catch (e) {
if (e instanceof ThemeArchiveExtractionError) {
setUploadError(e.message); // e.reason distinguishes too_many_files / too_large / invalid_archive
return;
}
throw e;
} Prevention
- Pre-scan the archive's entry count locally (unzip -l) before uploading to the browser editor.
- Exclude node_modules, .git, and generated asset folders when zipping a theme.
- For large themes, prefer server-side theme upload over the in-browser editor.
- Branch on ThemeArchiveExtractionError.reason to show a specific message.
When it happens
Trigger: extractThemeArchive is called with an ArrayBuffer whose zip contains > 1000 file entries (directories excluded by collectArchiveEntries). Common: a theme zip that included node_modules, a .git directory, generated/image-sprite folders, or multiple bundled themes.
Common situations: Theme developer ran a build that emitted thousands of files; user zipped the whole project folder instead of the dist output; a downloaded third-party theme ships heavy asset directories; CI artifact accidentally includes dev dependencies.
Related errors
- invalid_archive
- too_large
- Theme is not compatible or contains errors.
- A view with this name already exists
- The URL must be in a format like @username@instance.tld or h
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/9871f0a725ae4844.
Report an issue: GitHub.