linshenkx/prompt-optimizer · error · Error

S3 metadata lookup failed: ${s3ErrorMessage(error)}

Error message

S3 metadata lookup failed: ${s3ErrorMessage(error)}

What it means

HeadObject-style metadata lookup in the S3-compatible store failed with a non-404 error; the raw error is wrapped with s3ErrorMessage for context. 404s are converted to null, so this is a genuine AWS error (auth, network, permissions, bucket).

Source

Thrown at packages/ui/src/utils/remote-backup.ts:1582

    return Boolean(await this.head(path))
  }

  async head(path: string): Promise<RemoteObjectEntry | null> {
    const normalized = normalizeObjectPath(path)
    try {
      const response = await this.client.send(new HeadObjectCommand({
        Bucket: this.config.bucket,
        Key: this.keyForPath(normalized),
      }))
      return {
        path: normalized,
        sizeBytes: typeof response.ContentLength === 'number' ? response.ContentLength : undefined,
        updatedAt: response.LastModified instanceof Date ? response.LastModified.toISOString() : undefined,
        contentType: typeof response.ContentType === 'string' ? response.ContentType : undefined,
      }
    } catch (error) {
      if (isS3NotFoundError(error)) return null
      throw new Error(`S3 metadata lookup failed: ${s3ErrorMessage(error)}`, { cause: error })
    }
  }

  async put(
    path: string,
    body: Blob | ArrayBuffer | Uint8Array | string,
    options?: { contentType?: string },
  ): Promise<RemoteObjectEntry> {
    const normalized = normalizeObjectPath(path)
    const blob = bodyToBlob(body, options?.contentType || JSON_MIME_TYPE)
    const bytes = await bodyToUint8Array(blob)
    const contentType = blob.type || options?.contentType || JSON_MIME_TYPE
    try {
      await this.client.send(new PutObjectCommand({
        Bucket: this.config.bucket,
        Key: this.keyForPath(normalized),
        Body: bytes,
        ContentType: contentType,

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Check the access key/secret and endpoint/bucket in the provider config
  2. Verify IAM policy allows s3:HeadObject on the bucket
  3. Test connectivity: aws s3api head-object --bucket ... --key ... with the same credentials
Defensive patterns

Strategy: try-catch

Type guard

const isS3AuthError = (e: unknown): boolean => /AccessDenied|InvalidAccessKeyId|SignatureDoesNotMatch/.test(String((e as Error)?.cause?.message ?? ''))

Try / catch

try { await store.stat(path) } catch (e) { if (isS3AuthError(e)) refreshCredentials(); else throw e }

Prevention

When it happens

Trigger: stat(path) calling HeadObject with invalid credentials, wrong endpoint, non-existent bucket, network failure, or insufficient IAM permissions (s3:HeadObject).

Common situations: Expired/rotated access keys; wrong region/endpoint URL; IAM policy missing HeadObject; bucket deleted or renamed.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/fa81d4e071243576. Report an issue: GitHub.