{"record":{"id":"b791041c189589c6","repo":"hcengineering/platform","slug":"no-object-found","errorCode":null,"errorMessage":"no object found","messagePattern":"no object found","errorType":"exception","errorClass":null,"httpStatus":404,"severity":"error","filePath":"foundations/server/packages/s3/src/index.ts","lineNumber":327,"sourceCode":"        Bucket: this.getBucketId(wsIds),\n        Key: this.getDocumentKey(wsIds, objectName)\n      })\n      const rootPrefix = this.rootPrefix(wsIds)\n      return {\n        provider: '',\n        _class: core.class.Blob,\n        _id: this.stripPrefix(rootPrefix, objectName) as Ref<Blob>,\n        contentType: result.ContentType ?? '',\n        size: result.ContentLength ?? 0,\n        etag: result.ETag ?? '',\n        space: core.space.Configuration,\n        modifiedBy: core.account.System,\n        modifiedOn: result.LastModified?.getTime() ?? 0,\n        version: result.VersionId ?? null\n      }\n    } catch (err: any) {\n      if (err?.$metadata?.httpStatusCode !== 404) {\n        ctx.warn('no object found', { error: err, objectName, wsIds })\n        throw err\n      }\n    }\n  }\n\n  @withContext('get')\n  async get (ctx: MeasureContext, wsIds: WorkspaceIds, objectName: string): Promise<Readable> {\n    return await this.doGet(ctx, wsIds, objectName)\n  }\n\n  async doGet (ctx: MeasureContext, wsIds: WorkspaceIds, objectName: string, range?: string): Promise<Readable> {\n    try {\n      const res = await this.client.getObject({\n        Bucket: this.getBucketId(wsIds),\n        Key: this.getDocumentKey(wsIds, objectName),\n        Range: range\n      })\n","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/s3/src/index.ts#L309-L345","documentation":"stat looks up an object's metadata in S3. This log fires when the S3 HeadObject call fails with an unexpected (non-404) status — i.e. the lookup failed for a reason other than 'object absent' — and the underlying error is rethrown. Note the 404 case passes through silently; any other failure logs 'no object found' with the real error.","triggerScenarios":"Calling stat (directly or via saveFileToS3) when S3 returns errors such as 403 access denied, network/timeout failures, or missing bucket — anything where $metadata.httpStatusCode is not 404.","commonSituations":"Misconfigured AWS credentials or bucket policy revoking s3:GetObject; wrong region/endpoint config; S3 outages or throttling; VPC/network issues blocking the S3 endpoint.","solutions":["Inspect the logged inner error's $metadata.httpStatusCode and message","Fix AWS credentials/bucket policy so s3:HeadObject is allowed","Verify bucket name, region and endpoint configuration","Retry on transient network/5xx errors"],"exampleFix":"// before\nconst meta = await storage.stat(ctx, objectName, wsIds) // throws on 403\n// after\ntry {\n  const meta = await storage.stat(ctx, objectName, wsIds)\n} catch (err: any) {\n  if (err?.$metadata?.httpStatusCode === 404) return null // truly absent\n  throw err\n}","handlingStrategy":"try-catch","validationCode":"if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_REGION) {\n  throw new Error('S3 credentials/region not configured')\n}","typeGuard":"function isNotFound(err: any): boolean {\n  return err?.$metadata?.httpStatusCode === 404 || err?.name === 'NotFound'\n}","tryCatchPattern":"try {\n  meta = await storage.stat(ctx, objectName, wsIds)\n} catch (err: any) {\n  if (isNotFound(err)) {\n    meta = null // genuinely absent\n  } else if (isRetryable(err)) {\n    await retry(() => storage.stat(ctx, objectName, wsIds))\n  } else {\n    throw err\n  }\n}","preventionTips":["Pre-check IAM policy allows s3:HeadObject on the bucket","Verify bucket/region/endpoint config at service startup","Distinguish 404 from other errors — only 404 means 'absent'","Add retries with backoff for 5xx/network errors"],"tags":["typescript","aws","s3","network"],"backgroundTag":"s3-request-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}