{"record":{"id":"c80ec5d890e20ae4","repo":"usememos/memos","slug":"attachment-payload-is-missing","errorCode":null,"errorMessage":"attachment payload is missing","messagePattern":"attachment payload is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/attachment.go","lineNumber":284,"sourceCode":"\t\tif AttachmentNeedsInstanceStorageSetting(attachment) {\n\t\t\tinstanceStorageSetting, err := s.GetInstanceStorageSetting(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"failed to get instance storage setting\")\n\t\t\t}\n\t\t\treturn instanceStorageSetting, nil\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// ResolveAttachmentS3Driver resolves the storage driver referenced by an S3\n// attachment payload, validating the payload and supplying the instance setting.\nfunc (s *Store) ResolveAttachmentS3Driver(ctx context.Context, attachment *Attachment) (storage.Driver, *storepb.AttachmentPayload_S3Object, error) {\n\tif attachment == nil {\n\t\treturn nil, nil, errors.New(\"attachment is missing\")\n\t}\n\tif attachment.Payload == nil {\n\t\treturn nil, nil, errors.New(\"attachment payload is missing\")\n\t}\n\ts3Object := attachment.Payload.GetS3Object()\n\tif s3Object == nil {\n\t\treturn nil, nil, errors.New(\"S3 object payload is missing\")\n\t}\n\tif s3Object.Key == \"\" {\n\t\treturn nil, nil, errors.New(\"S3 object key is missing\")\n\t}\n\n\tinstanceStorageSetting, err := s.GetInstanceStorageSetting(ctx)\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"failed to get instance storage setting\")\n\t}\n\tdriver, err := ResolveStorageDriver(ctx, instanceStorageSetting, s3Object.StorageId, s3Object.S3Config)\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"failed to resolve storage driver\")\n\t}\n\treturn driver, s3Object, nil","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/store/attachment.go#L266-L302","documentation":"ResolveAttachmentS3Driver throws \"attachment payload is missing\" when the attachment exists but attachment.Payload is nil. Attachments created via legacy code paths or partially populated queries can lack the protobuf payload that identifies where the blob actually lives, so the storage driver cannot be resolved.","triggerScenarios":"Passing an attachment struct loaded without its payload column, or a hand-constructed Attachment{ID: ...} value with only scalar fields set.","commonSituations":"Rows written before the payload column existed (schema migration gaps); queries that select a subset of columns; test fixtures that omit Payload.","solutions":["Load the attachment through the normal store finder so the payload column is included","If the row genuinely has no payload, migrate or backfill payload data before using S3 features","Ensure test fixtures set Payload with a valid S3Object"],"exampleFix":"// before\natt := &store.Attachment{ID: id, StorageType: storepb.AttachmentStorageType_S3}\ndriver, obj, err := store.ResolveAttachmentS3Driver(ctx, att)\n// after\natt, err := store.GetAttachment(ctx, &store.FindAttachment{ID: &id}) // payload populated\n\ndriver, obj, err := store.ResolveAttachmentS3Driver(ctx, att)","handlingStrategy":"type-guard","validationCode":"if attachment == nil || attachment.Payload == nil {\n    return errors.New(\"attachment payload unavailable\")\n}","typeGuard":"func hasPayload(a *store.Attachment) bool {\n    return a != nil && a.Payload != nil\n}","tryCatchPattern":null,"preventionTips":["Load attachments via store finders that include the payload column","Keep test fixtures and migrations consistent so payload is always written"],"tags":["store","attachment","s3","payload"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}