{"record":{"id":"fa81d4e071243576","repo":"linshenkx/prompt-optimizer","slug":"s3-metadata-lookup-failed-s3errormessage-error","errorCode":null,"errorMessage":"S3 metadata lookup failed: ${s3ErrorMessage(error)}","messagePattern":"S3 metadata lookup failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/remote-backup.ts","lineNumber":1582,"sourceCode":"    return Boolean(await this.head(path))\n  }\n\n  async head(path: string): Promise<RemoteObjectEntry | null> {\n    const normalized = normalizeObjectPath(path)\n    try {\n      const response = await this.client.send(new HeadObjectCommand({\n        Bucket: this.config.bucket,\n        Key: this.keyForPath(normalized),\n      }))\n      return {\n        path: normalized,\n        sizeBytes: typeof response.ContentLength === 'number' ? response.ContentLength : undefined,\n        updatedAt: response.LastModified instanceof Date ? response.LastModified.toISOString() : undefined,\n        contentType: typeof response.ContentType === 'string' ? response.ContentType : undefined,\n      }\n    } catch (error) {\n      if (isS3NotFoundError(error)) return null\n      throw new Error(`S3 metadata lookup failed: ${s3ErrorMessage(error)}`, { cause: error })\n    }\n  }\n\n  async put(\n    path: string,\n    body: Blob | ArrayBuffer | Uint8Array | string,\n    options?: { contentType?: string },\n  ): Promise<RemoteObjectEntry> {\n    const normalized = normalizeObjectPath(path)\n    const blob = bodyToBlob(body, options?.contentType || JSON_MIME_TYPE)\n    const bytes = await bodyToUint8Array(blob)\n    const contentType = blob.type || options?.contentType || JSON_MIME_TYPE\n    try {\n      await this.client.send(new PutObjectCommand({\n        Bucket: this.config.bucket,\n        Key: this.keyForPath(normalized),\n        Body: bytes,\n        ContentType: contentType,","sourceCodeStart":1564,"sourceCodeEnd":1600,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/remote-backup.ts#L1564-L1600","documentation":"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).","triggerScenarios":"stat(path) calling HeadObject with invalid credentials, wrong endpoint, non-existent bucket, network failure, or insufficient IAM permissions (s3:HeadObject).","commonSituations":"Expired/rotated access keys; wrong region/endpoint URL; IAM policy missing HeadObject; bucket deleted or renamed.","solutions":["Check the access key/secret and endpoint/bucket in the provider config","Verify IAM policy allows s3:HeadObject on the bucket","Test connectivity: aws s3api head-object --bucket ... --key ... with the same credentials"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"const isS3AuthError = (e: unknown): boolean => /AccessDenied|InvalidAccessKeyId|SignatureDoesNotMatch/.test(String((e as Error)?.cause?.message ?? ''))","tryCatchPattern":"try { await store.stat(path) } catch (e) { if (isS3AuthError(e)) refreshCredentials(); else throw e }","preventionTips":["Rotate keys before expiry","Test HeadObject during provider setup"],"tags":["s3","aws-sdk","head-object","auth"],"backgroundTag":"s3-access-denied","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}