{"record":{"id":"1e66744c1dbb8b67","repo":"RocketChat/Rocket.Chat","slug":"failed-to-parse-app-json-e-instanceof-error-e","errorCode":null,"errorMessage":"Failed to parse app.json: ${e instanceof Error ? e.message : String(e)}","messagePattern":"Failed to parse app\\.json: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/meteor/client/views/marketplace/lib/getManifestFromZippedApp.ts","lineNumber":28,"sourceCode":"\t\tfileReader.onload = (e): void => resolve(new Uint8Array((e.target as any).result as Uint8Array));\n\t\tfileReader.onerror = (e): void => reject(e);\n\t\tfileReader.readAsArrayBuffer(file);\n\t});\n}\n\nfunction unzipAppBuffer(zippedAppBuffer: Uint8Array): Uint8ArrayObject {\n\treturn unzipSync(zippedAppBuffer);\n}\n\nfunction getAppManifest(unzippedAppBuffer: Uint8ArrayObject): AppManifestSchema {\n\tif (!unzippedAppBuffer['app.json']) {\n\t\tthrow new Error('No app.json file found in the zip');\n\t}\n\n\ttry {\n\t\treturn JSON.parse(strFromU8(unzippedAppBuffer['app.json']));\n\t} catch (e) {\n\t\tthrow new Error(`Failed to parse app.json: ${e instanceof Error ? e.message : String(e)}`);\n\t}\n}\n\nasync function unzipZippedApp(zippedApp: File | Uint8Array): Promise<Uint8ArrayObject> {\n\ttry {\n\t\tif (zippedApp instanceof File) {\n\t\t\tzippedApp = await fileToUint8Array(zippedApp);\n\t\t}\n\n\t\treturn unzipAppBuffer(zippedApp);\n\t} catch (e) {\n\t\tconsole.error(e);\n\t\tthrow e;\n\t}\n}\n\nexport async function getManifestFromZippedApp(zippedApp: File): Promise<AppManifestSchema> {\n\tconst unzippedBuffer = await unzipZippedApp(zippedApp);","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/client/views/marketplace/lib/getManifestFromZippedApp.ts#L10-L46","documentation":"getAppManifest() throws this wrapper around JSON.parse(strFromU8(unzippedAppBuffer['app.json'])) when the manifest bytes are present but are not valid JSON — the underlying SyntaxError message is embedded in the thrown string. The manifest is then expected to conform to AppManifestSchema, so this guard catches malformed manifests before schema validation.","triggerScenarios":"app.json containing JSON5-style syntax (comments, trailing commas, single quotes), a UTF-8 BOM or wrong encoding breaking the first token, minification/templating artifacts, or a truncated download leaving the file cut off.","commonSituations":"Hand-edited manifests with comments or trailing commas; manifests generated by templating tools that leave placeholders; Windows editors saving with BOM; app packages assembled by scripts that concatenate files.","solutions":["Run the manifest through a strict JSON validator (jq . app.json or JSON.parse in node) and fix the reported syntax error.","Remove comments and trailing commas; ensure plain double-quoted JSON.","Save as UTF-8 without BOM and rebuild the zip."],"exampleFix":"// before (app.json — invalid JSON)\n{\n  \"id\": \"my-app\",\n  \"version\": \"0.1.0\", // comments not allowed\n}\n\n// after\n{\n  \"id\": \"my-app\",\n  \"version\": \"0.1.0\"\n}","handlingStrategy":"validation","validationCode":"const raw = strFromU8(unzipped['app.json']).replace(/^\\uFEFF/, ''); // strip BOM\nJSON.parse(raw); // throws early with a precise position if invalid\n// then validate against AppManifestSchema before install","typeGuard":"const isValidManifestJson = (raw: string): boolean => {\n  try {\n    JSON.parse(raw);\n    return true;\n  } catch {\n    return false;\n  }\n};","tryCatchPattern":"try {\n  const manifest = getManifestFromZippedApp(file);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Failed to parse app.json')) {\n    // surface the embedded SyntaxError position to the app developer\n    dispatchToastMessage({ type: 'error', message: e.message });\n    return;\n  }\n  throw e;\n}","preventionTips":["Lint app.json with a strict JSON parser (jq, node JSON.parse) in CI.","No comments, no trailing commas, double quotes only, UTF-8 without BOM.","Generate manifests from tooling instead of hand-editing."],"tags":["apps-engine","marketplace","json"],"backgroundTag":"app-manifest-parse-failed","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}