toeverything/AFFiNE · error · CommentAttachmentNotFound
comment_attachment_not_found
comment_attachment_not_found
Error message
Comment attachment not found.
What it means
Thrown when commentAttachmentStorage.get returns neither a redirectUrl nor a body for the requested comment attachment key. The attachment object is missing from storage.
Source
Thrown at packages/backend/server/src/core/workspaces/controller.ts:393
@CallMetric('controllers', 'workspace_get_comment_attachment')
async commentAttachment(
@CurrentUser() user: CurrentUser,
@Param('id') workspaceId: string,
@Param('docId') docId: string,
@Param('key') key: string,
@Res() res: Response
) {
await this.ac.user(user.id).doc(workspaceId, docId).assert('Doc.Read');
const { body, metadata, redirectUrl } =
await this.commentAttachmentStorage.get(workspaceId, docId, key, true);
if (redirectUrl) {
return res.redirect(redirectUrl);
}
if (!body) {
throw new CommentAttachmentNotFound();
}
// metadata should always exists if body is not null
if (metadata) {
res.setHeader('content-type', metadata.contentType);
res.setHeader('last-modified', metadata.lastModified.toUTCString());
res.setHeader('content-length', metadata.contentLength);
} else {
this.logger.warn(
`Comment attachment ${workspaceId}/${docId}/${key} has no metadata`
);
}
applyAttachHeaders(res, {
contentType: metadata?.contentType,
filename: key,
});
res.setHeader('cache-control', 'private, max-age=2592000, immutable');View on GitHub (pinned to 26c515e050)
Solutions
- Verify the key and that the attachment still exists.
- Re-upload the attachment if lost.
- Check comment-attachment storage health and lifecycle rules.
- Hide broken attachment UI gracefully.
Example fix
// before
const { body } = await commentAttachmentStorage.get(ws, docId, key)
return body
// after
const { body, redirectUrl } = await commentAttachmentStorage.get(ws, docId, key, true)
if (redirectUrl) return res.redirect(redirectUrl)
if (!body) throw new NotFound('comment attachment missing') Defensive patterns
Strategy: validation
Validate before calling
const meta = await commentAttachmentStorage.head(workspaceId, docId, key) if (!meta) return brokenAttachmentPlaceholder(key)
Try / catch
try { await loadCommentAttachment(key) } catch (e) {
if (e.code === 'comment_attachment_not_found') showPlaceholder()
else throw e
} Prevention
- Track attachment lifecycle with comments.
- HEAD before rendering.
- Clean up orphaned keys.
When it happens
Trigger: Fetching a comment attachment by key when the object was deleted, never fully uploaded, or is not yet replicated.
Common situations: Attachment deleted with its comment; upload interrupted; object-store lifecycle removed it; wrong key.
Related errors
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/6ab3b0dfaf620823.
Report an issue: GitHub.