usememos/memos · error
S3 object payload is missing
Error message
S3 object payload is missing
What it means
ResolveAttachmentS3Driver throws "S3 object payload is missing" when attachment.Payload is present but its oneof content does not carry an S3Object (e.g. it only holds a LOCAL file descriptor). Only S3-backed attachments can be resolved to an S3 storage driver.
Source
Thrown at store/attachment.go:288
}
return instanceStorageSetting, nil
}
}
return nil, nil
}
// ResolveAttachmentS3Driver resolves the storage driver referenced by an S3
// attachment payload, validating the payload and supplying the instance setting.
func (s *Store) ResolveAttachmentS3Driver(ctx context.Context, attachment *Attachment) (storage.Driver, *storepb.AttachmentPayload_S3Object, error) {
if attachment == nil {
return nil, nil, errors.New("attachment is missing")
}
if attachment.Payload == nil {
return nil, nil, errors.New("attachment payload is missing")
}
s3Object := attachment.Payload.GetS3Object()
if s3Object == nil {
return nil, nil, errors.New("S3 object payload is missing")
}
if s3Object.Key == "" {
return nil, nil, errors.New("S3 object key is missing")
}
instanceStorageSetting, err := s.GetInstanceStorageSetting(ctx)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to get instance storage setting")
}
driver, err := ResolveStorageDriver(ctx, instanceStorageSetting, s3Object.StorageId, s3Object.S3Config)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to resolve storage driver")
}
return driver, s3Object, nil
}
// AttachmentNeedsInstanceStorageSetting reports whether cleanup should load
// the configured storage registry for an S3 attachment.View on GitHub (pinned to 14d757ce1f)
Solutions
- Branch on attachment.StorageType (or payload.GetS3Object() != nil) before calling ResolveAttachmentS3Driver
- Use the local file path for LOCAL attachments instead of S3 resolution
- Verify the payload oneof is set to s3_object when writing S3 attachments
Example fix
// before
driver, obj, err := store.ResolveAttachmentS3Driver(ctx, att) // att is LOCAL
// after
if att.Payload.GetS3Object() == nil {
return serveLocalFile(att)
}
driver, obj, err := store.ResolveAttachmentS3Driver(ctx, att) Defensive patterns
Strategy: type-guard
Validate before calling
if attachment.Payload.GetS3Object() == nil {
// not S3-backed; use the local path instead
} Type guard
func isS3Attachment(a *store.Attachment) bool {
return a != nil && a.Payload != nil && a.Payload.GetS3Object() != nil
} Prevention
- Branch on StorageType / payload oneof before choosing S3 vs local handling
- Set the payload oneof correctly when creating attachments
When it happens
Trigger: Calling S3 resolution on an attachment whose StorageType is LOCAL, or whose payload oneof is unset/holds a different message type.
Common situations: Instance switched from S3 to local storage but old code paths still try S3 resolution for all attachments; branching on the wrong field before choosing the resolution path.
Related errors
- attachment is missing
- attachment payload is missing
- S3 object key is missing
- Internal
- default storage is not configured
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/bdaabd9f20f55204.
Report an issue: GitHub.