{"record":{"id":"274ab5d0e8b715d1","repo":"mastra-ai/mastra","slug":"blob-not-found-for-hash-entry-blobhash-file","errorCode":null,"errorMessage":"Blob not found for hash ${entry.blobHash} (file: ${path})","messagePattern":"Blob not found for hash (.+?) \\(file: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/core/src/workspace/skills/versioned-skill-source.ts","lineNumber":116,"sourceCode":"        createdAt: this.#versionCreatedAt,\n        modifiedAt: this.#versionCreatedAt,\n      };\n    }\n\n    throw new Error(`Path not found in skill version tree: ${path}`);\n  }\n\n  async readFile(path: string): Promise<string | Buffer> {\n    const normalized = this.#normalizePath(path);\n    const entry = this.#tree.entries[normalized];\n\n    if (!entry) {\n      throw new Error(`File not found in skill version tree: ${path}`);\n    }\n\n    const blob = await this.#blobStore.get(entry.blobHash);\n    if (!blob) {\n      throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path})`);\n    }\n\n    // Decode base64-encoded binary content back to Buffer\n    if (entry.encoding === 'base64') {\n      return Buffer.from(blob.content, 'base64');\n    }\n\n    return blob.content;\n  }\n\n  async readdir(path: string): Promise<SkillSourceEntry[]> {\n    const normalized = this.#normalizePath(path);\n\n    if (!this.#directories.has(normalized)) {\n      throw new Error(`Directory not found in skill version tree: ${path}`);\n    }\n\n    const prefix = normalized === '' ? '' : normalized + '/';","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/skills/versioned-skill-source.ts#L98-L134","documentation":"After finding a valid tree entry, VersionedSkillSource.readFile fetches content from the BlobStore by the entry's blobHash; if the blob store returns nothing, the manifest references content that is missing from storage. This indicates storage-level corruption or incomplete retention: the version tree metadata survived but its blob did not.","triggerScenarios":"Calling readFile on a file whose blobHash is not present in the configured BlobStore — blob was deleted by retention/GC, storage backend was swapped or reset, partial publish wrote the tree without all blobs, or reading with a BlobStore instance pointed at a different database/prefix.","commonSituations":"Environments pruning old blobs while old skill versions remain listed; restoring storage from a partial backup; switching between dev/prod storage DBs; concurrent publish bugs leaving trees without blobs.","solutions":["Republish the skill version so blobs are rewritten and the tree matches stored content.","Verify the BlobStore instance is connected to the same storage that holds the published blobs (same DB/prefix).","Check blob retention/GC policies so blobs for live versions aren't deleted.","Restore missing blobs from backup, or delete the broken version and re-publish."],"exampleFix":"// before\nconst src = new VersionedSkillSource(tree, devBlobStore, createdAt); // blobs live in prod store\n// after\nconst src = new VersionedSkillSource(tree, prodBlobStore, createdAt);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await versioned.readFile(path);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Blob not found for hash')) {\n    logger.error({ path }, 'Skill blob missing from store; version is corrupt — republish required');\n    throw new SkillCorruptError(path, { cause: err });\n  }\n  throw err;\n}","preventionTips":["Never run blob GC/retention on blobs referenced by live skill versions.","Publish atomically: write all blobs before committing the version tree.","Point the source at the same storage backend used at publish time.","Monitor for orphaned trees via a periodic tree-vs-blob integrity check."],"tags":["storage","skills","blob-store","data-integrity"],"backgroundTag":"blob-missing-from-store","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}