{"record":{"id":"603e2457f3526139","repo":"toeverything/AFFiNE","slug":"blob-not-found","errorCode":"blob_not_found","errorMessage":"Blob ${blobId} not found in Space ${spaceId}.","messagePattern":"Blob (.+?) not found in Space (.+?)\\.","errorType":"exception","errorClass":"BlobNotFound","httpStatus":404,"severity":"error","filePath":"packages/backend/server/src/core/workspaces/controller.ts","lineNumber":137,"sourceCode":"    const { body, metadata, redirectUrl } = await this.storage.get(\n      workspaceId,\n      name,\n      true\n    );\n\n    if (redirectUrl) {\n      // redirect to signed url\n      if (redirect === 'manual') {\n        return res.send({\n          url: redirectUrl,\n        });\n      } else {\n        return res.redirect(redirectUrl);\n      }\n    }\n\n    if (!body) {\n      throw new BlobNotFound({\n        spaceId: workspaceId,\n        blobId: name,\n      });\n    }\n\n    // metadata should always exists if body is not null\n    if (metadata) {\n      res.setHeader(\n        'content-type',\n        metadata.contentType.startsWith('application/json') // application/json is reserved for redirect url\n          ? 'text/json'\n          : metadata.contentType\n      );\n      res.setHeader('last-modified', metadata.lastModified.toUTCString());\n      res.setHeader('content-length', metadata.contentLength);\n    } else {\n      this.logger.warn(`Blob ${workspaceId}/${name} has no metadata`);\n    }","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/workspaces/controller.ts#L119-L155","documentation":"Thrown after the storage layer returned no body (and no redirectUrl) for the requested blob name. The blob record may be absent, deleted, or not yet replicated to the object store.","triggerScenarios":"GET /workspaces/:id/blobs/:name passes access checks, storage returns a null body with no redirectUrl, so BlobNotFound is thrown.","commonSituations":"Blob was deleted; upload incomplete/corrupted record; object-store replication lag; wrong blob name; an expired object lifecycle rule removed it.","solutions":["Verify the blob name is correct and the blob exists in storage.","Re-upload the blob if it was lost.","Check object storage lifecycle/replication and the blob record status.","Retry shortly if this follows a fresh upload."],"exampleFix":"// before\nconst { body } = await storage.get(ws, name)\nreturn body\n// after\nconst { body, redirectUrl } = await storage.get(ws, name, true)\nif (redirectUrl) return res.redirect(redirectUrl)\nif (!body) throw new NotFound('blob missing')","handlingStrategy":"validation","validationCode":"const meta = await storage.head(workspaceId, name)\nif (!meta) return placeholderAsset(name)","typeGuard":null,"tryCatchPattern":"try { await loadBlob(ws, name) } catch (e) {\n  if (e.code === 'blob_not_found') showPlaceholder()\n  else throw e\n}","preventionTips":["HEAD the blob before linking.","Keep blob lifecycle/delete in sync with references.","Use immutable names/ids."],"tags":["blobs","not-found","storage","object-store"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}