Skip to content

fix(gcp): type HTTP 412 on storage objects.delete and objects.patch - #877

Merged
sam-goodwin merged 1 commit into
alchemy-run:mainfrom
duailibe:gcs-state-store-precondition
Oct 14, 2026
Merged

sam-goodwin merged 1 commit into
alchemy-run:mainfrom
duailibe:gcs-state-store-precondition

Conversation

@duailibe

Copy link
Copy Markdown
Contributor

objects.delete and objects.patch return HTTP 412 when an ifGenerationMatch or ifMetagenerationMatch precondition does not hold (docs). 412 is not in the core status map, so today it lands as UnknownGCPError. A caller doing compare-and-swap cannot tell "another writer changed the object" from a real failure without matching on the HTTP status.

Alchemy needs this for a GCS state store. Its lock is one object per stack and stage. A deploy refreshes the lock with a metadata patch and releases it with a delete, both guarded by the generation it created. A 412 means another deploy took the lock over, so the caller has to handle it by tag:

storage.deleteObjects({ bucket, object, ifGenerationMatch: generation }).pipe(
  // Already gone, or taken over after it expired: nothing of ours is left.
  Effect.catchTag(["NotFound", "ObjectPreconditionFailed"], () => Effect.void),
);

This adds ObjectPreconditionFailed, matched on { status: 412 }, to both operations, the same way setIamPolicyBucketsEtagMismatch.json types 412 on buckets. GCS also uses 412 for orgPolicyConstraintFailed and for soft-delete restore errors, which do not apply to these two operations in practice.

A failed ifGenerationMatch / ifMetagenerationMatch precondition on
objects.delete or objects.patch landed as UnknownGCPError, because 412 is
not in the core status map. Callers doing compare-and-swap (alchemy's GCS
state-store lock) could not tell a lost race from a real failure.

Add ObjectPreconditionFailed (status 412) to both operations.
@alchemy-version-bot

Copy link
Copy Markdown
Contributor

Install the packages built from this commit:

@distilled.cloud

pnpm install https://pkg.distilled.cloud/@distilled.cloud/acme/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/adyen/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/apache-superset/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/archil/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/argocd/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/auth0/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/aws/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/axiom/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/azure/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/boat-dev/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/celld/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/chronosphere/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/clerk/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/cloudflare/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/coinbase/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/coolify/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/core/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/customerio/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/datadog/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/daytona/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/digitalocean/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/discord/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/docker/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/doppler/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/elasticsearch/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/expo-eas/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/fly-io/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/forgejo/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/gcp/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/github/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/google-workspace/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/grafana/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/growthbook/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/gusto/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/hetzner/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/hostinger/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/huggingface/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/iceberg/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/infisical/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/inngest/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/intercom/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/kubernetes/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/launchdarkly/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/meilisearch/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/mercury/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/metabase/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/modal/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/modrinth/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/mongodb-atlas/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/neon/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/notion/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/okta/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/onepassword/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/opencode/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/ovh/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/paypal/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/plaid/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/planetscale/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/polar/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/porkbun/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/posthog/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/prisma/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/railway/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/redis-cloud/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/remote/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/render/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/resend/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/s2/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/sentry/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/slack/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/spacetimedb/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/squarespace/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/stackit/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/stripe/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/supabase/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/surrealdb/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/temporal/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/trigger-dev/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/turbopuffer/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/turso/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/typesense/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/unkey/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/vanta/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/vercel/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/whop/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/workos/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/xata/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/zendesk/pr:877:c722e18
pnpm install https://pkg.distilled.cloud/@distilled.cloud/zerossl/pr:877:c722e18

Published Oct 14, 2026, 10:40 AM UTC. Expires Oct 21, 2026, 10:40 AM UTC, extended while this pull request is open.

@sam-goodwin
sam-goodwin merged commit 4cd6267 into alchemy-run:main Oct 14, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants