RocketChat/Rocket.Chat · error

No app.json file found in the zip

Error message

No app.json file found in the zip

What it means

Thrown by getAppManifest when the unzipped app archive does not contain an 'app.json' file at its root. The function unzips the app bundle (a zip archive) using unzipSync from the fflate library and checks for the 'app.json' key. Every Rocket.Chat app must have an app.json manifest at the zip root describing its name, version, classFile, and other metadata.

Source

Thrown at apps/meteor/client/views/marketplace/lib/getManifestFromZippedApp.ts:22

type Uint8ArrayObject = { [fileName: string]: Uint8Array };
type AppManifestSchema = { id: string; name: string; permissions: AppPermission[] };

async function fileToUint8Array(file: File): Promise<Uint8Array> {
	return new Promise((resolve, reject) => {
		const fileReader = new FileReader();
		fileReader.onload = (e): void => resolve(new Uint8Array((e.target as any).result as Uint8Array));
		fileReader.onerror = (e): void => reject(e);
		fileReader.readAsArrayBuffer(file);
	});
}

function unzipAppBuffer(zippedAppBuffer: Uint8Array): Uint8ArrayObject {
	return unzipSync(zippedAppBuffer);
}

function getAppManifest(unzippedAppBuffer: Uint8ArrayObject): AppManifestSchema {
	if (!unzippedAppBuffer['app.json']) {
		throw new Error('No app.json file found in the zip');
	}

	try {
		return JSON.parse(strFromU8(unzippedAppBuffer['app.json']));
	} catch (e) {
		throw new Error(`Failed to parse app.json: ${e instanceof Error ? e.message : String(e)}`);
	}
}

async function unzipZippedApp(zippedApp: File | Uint8Array): Promise<Uint8ArrayObject> {
	try {
		if (zippedApp instanceof File) {
			zippedApp = await fileToUint8Array(zippedApp);
		}

		return unzipAppBuffer(zippedApp);
	} catch (e) {
		console.error(e);

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Ensure app.json is at the root of the zip archive, not inside a subdirectory. Zip the contents, not the parent folder.
  2. Verify the zip is a valid Rocket.Chat app by checking its structure before uploading.
  3. Use the app build tool (rc-apps) which correctly packages the app with app.json at root.
  4. If unzipping from a File object, ensure it was read correctly as an ArrayBuffer/Uint8Array.

Example fix

# before: zips the folder, creating myapp/app.json
cd parent && zip -r myapp.zip myapp/
# after: zip from inside the app directory so app.json is at root
cd myapp && zip -r ../myapp.zip .
Defensive patterns

Strategy: validation

Validate before calling

const entries = Object.keys(unzippedAppBuffer);
if (!entries.includes('app.json')) {
  throw new Error('This zip is not a valid Rocket.Chat app: missing app.json at root');
}

Type guard

const hasAppJsonAtRoot = (entries: string[]): boolean =>
  entries.includes('app.json');

Try / catch

try {
  const manifest = await getManifestFromZippedApp(zipFile);
} catch (e) {
  if (e instanceof Error && e.message === 'No app.json file found in the zip') {
    showInvalidAppError();
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: The uploaded zip file is not a valid Rocket.Chat app archive. The app.json file exists but in a subdirectory instead of the zip root. The zip was created incorrectly (e.g., zipping a folder rather than its contents). A non-app zip file was uploaded by mistake.

Common situations: Developer zips the project folder (creating folder/app.json instead of app.json at root). User uploads the wrong file (e.g., a theme or asset zip). App build process changed and no longer includes app.json at root. Corrupted or truncated zip file.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/d4dc2b7fef65b538. Report an issue: GitHub.