{"record":{"id":"dc72c1186e8e017f","repo":"moeru-ai/airi","slug":"extension-manifest-does-not-exist-manifestpath","errorCode":null,"errorMessage":"Extension manifest does not exist: ${manifestPath}","messagePattern":"Extension manifest does not exist: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts","lineNumber":207,"sourceCode":"      }\n      if (!stats.isFile()) {\n        throw new Error(`Extension packages can contain only files and directories: ${relativePath}`)\n      }\n      totalBytes += stats.size\n      if (totalBytes > extensionPackageLimits.totalBytes) {\n        throw new Error('Extension package exceeds the 512 MiB size limit.')\n      }\n      files.push({ path, relativePath, size: stats.size })\n    }\n  }\n\n  directories.sort()\n  files.sort((left, right) => left.relativePath.localeCompare(right.relativePath))\n\n  const manifestRelativePath = relative(sourceRealPath, manifestPath)\n  const manifestFile = files.find(file => file.relativePath === manifestRelativePath)\n  if (!manifestFile) {\n    throw new Error(`Extension manifest does not exist: ${manifestPath}`)\n  }\n  if (manifestFile.size > extensionPackageLimits.manifestBytes) {\n    throw new Error('Extension manifest exceeds the 1 MiB size limit.')\n  }\n\n  // The manifest remains the only retained byte snapshot because the preview\n  // and fingerprint must describe the same manifest contents. The stable file\n  // handle limits the allocation even if another process grows the path.\n  const manifestContents = await readManifestSnapshot(manifestFile.path, manifestFile.size)\n\n  let rawManifest: unknown\n  try {\n    rawManifest = JSON.parse(manifestContents.toString('utf8')) as unknown\n  }\n  catch (error) {\n    if (error instanceof SyntaxError) {\n      throw new Error(`Extension manifest is not valid JSON: ${error.message}`)\n    }","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/apps/stage-tamagotchi/src/main/services/airi/plugins/host/directory-import.ts#L189-L225","documentation":"After the walk, the collected file list is searched for the manifest's relative path. If the manifest file was not found among the walked entries, this error is thrown. It usually means the file disappeared between the assertRegularFile check and the end of the walk, or the walk did not reach the path where the manifest was checked.","triggerScenarios":"Calling inspectExtensionDirectory when the expected manifest file (join(sourceRealPath, extensionManifestFileName)) was missing at walk time — deleted or renamed after the initial assertRegularFile, or present as a symlink/special file (filtered out by earlier checks).","commonSituations":"A build step renamed manifest.json mid-import; the manifest is a symlink to a shared file (rejected earlier by the symlink rule); the user edited/deleted the manifest while the import dialog was open; case-sensitivity mismatch (Manifest.json vs manifest.json on Linux).","solutions":["Ensure a file named exactly per extensionManifestFileName (e.g. manifest.json, correct case) exists at the root of the selected folder, then retry.","Replace a symlinked manifest with a real file copy.","Stop concurrent build/edit processes modifying the folder and re-select it.","Re-extract or re-copy the extension package; the copy may be incomplete."],"exampleFix":"// before: folder has Manifest.json (wrong case on Linux)\nawait inspected('my-ext/') // -> manifest not found\n// after\n// mv my-ext/Manifest.json my-ext/manifest.json\nawait inspected('my-ext/')","handlingStrategy":"validation","validationCode":"import { access, constants } from 'node:fs/promises'\nimport { join } from 'node:path'\nawait access(join(folder, 'manifest.json'), constants.R_OK) // throws if manifest missing/unreadable","typeGuard":null,"tryCatchPattern":"try {\n  await inspected(folder)\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith('Extension manifest does not exist')) {\n    showUserError('The selected folder has no manifest.json at its root; check name/case and re-select.')\n    return\n  }\n  throw error\n}","preventionTips":["Verify a real (non-symlink) manifest.json sits at the folder root before importing.","Watch filename case on case-sensitive filesystems (manifest.json vs Manifest.json).","Don't edit or regenerate the manifest while an import is in progress."],"tags":["filesystem","extensions","manifest","file-not-found"],"backgroundTag":"file-not-found","analyzedSha":"438a067dde47aa0bdb46c2323d1fe293dc805218","analyzedAt":"2026-09-17T01:14:42.644Z","contentChangedAt":"2026-09-17T01:14:42.644Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}