Skip to content

add-project: first-use fails — isNotFound() regex misses S3 "does not exist" message (NoSuchKey treated as fatal) #713

@marcusrbrown

Description

@marcusrbrown

Summary

On a freshly deployed gateway (v0.46.2), the first-ever /fro-bot add-project <url> always fails with "Internal error checking existing bindings. Please try again." Retrying does not help — it fails identically every time, because the daemon errors out before it ever writes the first binding. This is a deterministic first-use deadlock for add-project on any new gateway.

Reproduction

  1. Deploy a fresh gateway with an empty object-store bindings prefix (zero bindings).
  2. In the guild, run /fro-bot add-project https://github.com/owner/repo.
  3. The command passes URL validation, enters PRE_FLIGHT, and aborts with "Internal error checking existing bindings."

Daemon logs

{"level":"info","phase":"PRE_FLIGHT","outcome":"start","msg":"add-project phase"}
{"level":"warn","errorCode":"NoSuchKey","errorName":"NoSuchKey","httpStatusCode":404,"message":"The specified key does not exist.","msg":"Object store getObject failed"}
{"level":"error","phase":"PRE_FLIGHT","errorKind":"Object store getObject failed: The specified key does not exist.","msg":"add-project: store error during pre-flight lookup"}

The 404 NoSuchKey is a valid S3 response — it confirms object-store credentials, connectivity, and the egress allowlist all work. The binding key simply doesn't exist yet because this is the first add-project.

Root cause

packages/gateway/src/bindings/store.ts classifies "key absent" via:

function isNotFound(error: Error): boolean {
  return /not.?found|no.?such.?key|404/i.test(error.message)
}

But the error reaching this check has the message produced by the object-store adapter:

Object store getObject failed: The specified key does not exist.

That string contains none of not found, no such key, or 404 (AWS's human-readable message is "The specified key does not exist."; NoSuchKey is the SDK error code, not the message). So isNotFound() returns false, the absent key is treated as a fatal store failure, and the pre-flight lookup aborts instead of proceeding to create the first binding.

Verified empirically:

/not.?found|no.?such.?key|404/i.test("Object store getObject failed: The specified key does not exist.")
// => false   (bug: expected 404 treated as fatal)

Suggested fix

Smallest change — also match the AWS message text:

function isNotFound(error: Error): boolean {
  return /not.?found|no.?such.?key|does.?not.?exist|404/i.test(error.message)
}

More robust — preserve and check the SDK error code (NoSuchKey) directly in the object-store adapter, falling back to the message regex for non-AWS S3-compatible stores. Matching on the code avoids future drift if a provider's message wording differs.

Affected versions

Present in v0.46.2 and still present on the v0.47.0 line (same isNotFound implementation). Any deployment whose object store returns the AWS-style "The specified key does not exist." message is affected; the first add-project can never succeed until this is patched.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions