Forge diagnostics are stable contracts for remediation and automation. A failed build, provider publication, domain reconciliation, and production activation are separate states; fixing one does not authorize the next.
| Diagnostic | Meaning | Operator action |
|---|---|---|
FORGE_CONFIG_MISSING |
The selected project root has no forgeBuild.ts. |
Add the manifest inside that project root. |
FORGE_CONFIG_CHANGED |
The checkout no longer matches the frozen exact-SHA manifest. | Treat the build as compromised or stale; schedule the intended SHA again. |
| Private source unauthorized | The run, repository, account, project, SHA, or frozen entitlement receipt does not match. | Do not bypass it; correct the scheduling or ownership record. |
| Unsafe source projection | A path escapes the project/workspace closure, or a symlink/special file is present. | Remove the unsafe source shape. |
| Signal | Meaning | Action |
|---|---|---|
GIT_INGEST_PACK_TOO_LARGE / Git pack exceeds the 490000000-byte ingest limit |
One receive-pack request crossed Forge's provider-safe 490 MB boundary. The durable ingest diagnostic records the observed pack bytes as terminal rather than suggesting an unchanged retry. | Split the migration into incremental pushes or adopt large blobs into Forge Assets before retrying. |
unpack failed; request <id> |
The trusted native-Git runner rejected or could not persist the pack before ref mutation. The request ID identifies the structured git_streaming_ingest_failed log, including phase and bounded runner error. |
Look up the request ID; do not assume corruption or retry a large pack until the recorded phase is understood. The repository ref is unchanged. |
Native Git pack validation failed |
Native checksum, object, or delta validation rejected the received bytes. | Recreate the pack from a verified local repository and inspect the bounded native-Git detail. |
Runner release transitions are retried inside the original receive-pack request.
A matching runner in draining continues accepting staged Git ingest, while a
successor in verifying returns a transient response and the repository Worker
retains the pack. Correlate git_ingest_handoff_retry events with release state;
a normal runner release must not surface as unpack failed.
Duplicate immutable objects are discovered before sandbox streams are opened. If another ingest wins the same content-addressed key concurrently, Forge cancels the unused conditional-upload body so receive-pack cannot remain backpressured. Ref mutation still occurs only after every required object is available.
Configuration validation uses stable, machine-readable issue codes:
| Diagnostic | Meaning | Remediation |
|---|---|---|
assets_config_invalid_json / assets_config_invalid |
.forge/assets.json is not valid JSON or is not an object. |
Repair the root file; do not move configuration into a project subdirectory. |
assets_config_too_large |
The source exceeds 64 KiB. | Reduce it to reviewed literal entries. |
assets_config_unknown_field / assets_entry_unknown_field |
The strict v1 contract found an unsupported field. | Remove the field or adopt a later documented schema version. |
assets_config_schema / assets_config_version / assets_config_mode |
The schema URL, version, or mode is not the Forge Assets v1 contract. | Use the v1 schema, version 1, and hybrid mode. |
assets_config_entries |
Entries are absent, empty, or exceed 1,000. | Add at least one entry or split/reduce the reviewed selection. |
assets_entry_invalid / assets_entry_kind |
An entry is malformed or is not a file or tree. |
Use the public schema and a literal entry object. |
assets_entry_unsafe_path / assets_entry_overlap |
A path is non-normalized, unsafe, duplicated, or covered by another tree entry. | Use unique, non-overlapping repository-relative literal paths. |
assets_entry_missing / assets_entry_unsupported_type |
Adoption found a missing path, symlink, submodule, or special file. | Refresh the inspection and select contained regular files at that commit. |
assets_lfs_pointer_invalid |
Existing LFS metadata is not a canonical SHA-256 pointer and size. | Regenerate the pointer with standard Git LFS tooling or re-upload through Forge migration. |
The administrator-only adoption API additionally returns:
| Diagnostic | Meaning | Remediation |
|---|---|---|
invalid_source / invalid_target_branch / stale_head |
The exact SHA or primary branch no longer matches the inspected head. | Inspect again; never apply a stale selection. |
invalid_asset_selection / proposal_mismatch / asset_selection_size |
Entries are invalid, outside the exact-source proposal, or exceed the migration bound. | Submit only reviewed literal entries returned by the latest inspection. |
asset_object_set_mismatch / asset_identity_mismatch |
Submitted paths, Git blob SHAs, OIDs, or sizes do not exactly match the frozen source. | Discard stale object metadata and inspect again. |
assets_not_uploaded |
One or more selected digest objects are not verified and reachable by this repository/account. | Upload the reported missing objects through the standard Forge LFS HTTP API, then inspect again. A local git-lfs binary is optional. |
asset_content_mismatch |
Stored bytes do not equal the selected ordinary Git blob despite the submitted identity. | Quarantine/re-upload the object; do not open the migration PR. |
idempotency_conflict |
The idempotency key was already used for different input. | Retry the original body or create a new key for the changed request. |
asset_storage_unavailable |
The trusted SITE_ASSETS binding is absent. |
Stop before Git mutation and restore the binding. |
Successful adoption returns an immutable receipt and suppresses the generated migration pull request's automatic Deploy preview. It does not change the production branch or deploy a release. The suppression is durable: a receipt backed migration pull request cannot later be changed to ordinary preview behavior; create a separate ordinary pull request for a deployable revision.
The trusted runner emits these live build/publication failures:
| Diagnostic | Meaning | Remediation |
|---|---|---|
FORGE_ASSETS_CONFIG_INVALID |
The committed root asset config failed the strict parser. | Correct the reported parser issue codes. |
FORGE_ASSETS_POINTER_SCAN_FAILED |
The exact checkout could not be inspected for tracked pointers. | Retry once, then investigate source materialization and Git index integrity. |
FORGE_ASSETS_ACCOUNT_REQUIRED |
A pointer build has no authorized owning account. | Repair project/repository ownership and reschedule the exact SHA. |
FORGE_ASSETS_STORAGE_UNAVAILABLE |
The trusted asset binding is missing. | Stop the release and provision the declared SITE_ASSETS binding. |
FORGE_ASSET_UNAVAILABLE |
The repository/account cannot reach the declared digest and size. | Upload and verify the object for this repository; never infer cross-account existence. |
FORGE_ASSET_POINTER_CHANGED / FORGE_ASSET_POINTER_INVALID |
A pointer disappeared or stopped matching the canonical v1 format during inspection. | Treat the output as non-quiescent or corrupt and rebuild the frozen source. |
FORGE_ASSET_STORAGE_MISMATCH |
R2 size or SHA-256 no longer matches verified metadata. | Quarantine the object and re-upload verified bytes. |
FORGE_ASSET_OUTPUT_CONFLICT |
OpenNext changed a public pointer Forge expected to publish unchanged. | Remove the deploy-time declaration or make the build leave that public file unchanged. |
FORGE_ASSET_PROVIDER_LIMIT |
A verified object exceeds the connected provider's per-file ceiling. | Reduce the file before publication; source entitlement does not override provider limits. |
Git LFS transfer errors use the standard per-object HTTP status contract:
| Status | Meaning | Remediation |
|---|---|---|
401 / 403 |
Authentication, current repository permission, account state, or entitlement failed. | Refresh Forge Git credentials and confirm repository/account authorization. |
404 |
The digest is not reachable from this repository, even if identical physical bytes exist elsewhere. | Push or adopt the object for this repository; do not infer cross-account existence. |
409 |
One digest was declared with conflicting sizes. | Treat the pointer or request as corrupt and regenerate it. |
413 |
The object, account logical usage, batch, or active request transport exceeds its bound. | Reduce/split the migration or request an entitlement; a 1 GiB safety ceiling does not override the Worker request-body limit. |
422 |
The batch, lowercase SHA-256 OID, declared size, Content-Length, checksum, or verify body is invalid. |
Correct the client request or source bytes and start a new transfer. |
503 |
Signing, verified storage, or the asset service is temporarily unavailable. | Retry the same digest idempotently after service health is restored. |
Transfer tickets are short lived and current repository permission is checked again when redeemed. A ticket that was valid before access revocation must not be treated as durable authority.
| Diagnostic | Meaning | Remediation |
|---|---|---|
FORGE_OPENNEXT_PROJECT_INVALID |
The project root or package shape is invalid. | Check the project root and package.json. |
FORGE_OPENNEXT_PACKAGE_INVALID |
Project or installed package metadata is malformed. | Repair package.json and the frozen install. |
FORGE_OPENNEXT_DEPENDENCY_REQUIRED |
The project does not declare @opennextjs/cloudflare. |
Add it to the project package. |
FORGE_OPENNEXT_DEPENDENCY_UNPINNED |
The declaration bypasses the frozen registry lockfile, uses an implicit tag, or is otherwise unbounded. | Use a registry semver declaration and update the frozen lockfile. |
FORGE_OPENNEXT_LOCKFILE_REQUIRED |
No supported frozen-install lockfile proves the dependency. | Commit the root lockfile. |
FORGE_OPENNEXT_VERSION_UNSUPPORTED |
The frozen OpenNext version is not the vetted adapter target, or the installed Next.js version is outside its peer range. For OpenNext 1.19.11 the Next range is `>=15.5.18 <16 | |
FORGE_OPENNEXT_LOCAL_CLI_MISSING |
Frozen install did not produce the project-local executable. | Repair the lockfile/install; never fall back to latest. |
FORGE_OPENNEXT_VERSION_INVALID |
Installed metadata does not match the exact declaration. | Regenerate the lockfile and frozen dependencies. |
FORGE_OPENNEXT_WRANGLER_CONTRACT_INVALID |
Wrangler does not point at Forge-derived OpenNext output or required compatibility settings. | Use .open-next/worker.js, .open-next/assets, ASSETS, nodejs_compat, and a supported compatibility date. R2 identity is checked separately against inherited production bindings. |
| Diagnostic | Meaning | Remediation |
|---|---|---|
FORGE_OPENNEXT_OUTPUT_MISSING |
Required Worker, asset, module, or cache output is absent. | Inspect the OpenNext build logs and adapter compatibility. |
FORGE_OPENNEXT_OUTPUT_UNSAFE |
Output contains an unsafe path, duplicate, symlink, or special file. | Make output a contained regular-file tree. |
FORGE_OPENNEXT_COMPILER_INPUT_OVERFLOW |
The raw .open-next compiler-input tree exceeded its entry, file, symlink, path, single-file, or aggregate bound. |
Reduce the traced build input. Do not raise provider module limits to admit raw compiler dependencies. |
FORGE_OPENNEXT_OUTPUT_CHANGED |
Output changed while trusted ingest inspected it. | Stop background writers and rebuild from a quiesced process tree. |
FORGE_OPENNEXT_MODULE_OVERFLOW |
The Wrangler-compiled module graph exceeded its raw module limit. | Reduce/split generated Worker output; raw .open-next dependencies are not counted as provider modules. |
FORGE_OPENNEXT_ASSET_OVERFLOW |
Asset count, file, path, or aggregate limits were exceeded. | Reduce assets or request an entitlement where the provider permits it. |
FORGE_OPENNEXT_CACHE_OVERFLOW |
ISR seed limits were exceeded. | Reduce the initial cache seed; runtime regeneration remains separate. |
FORGE_OPENNEXT_WORKER_COMPRESSED_SIZE |
The gzip-compressed Worker exceeds the supported ceiling. | Reduce server dependencies or generated code. |
FORGE_OPENNEXT_CACHE_LAYOUT_UNSUPPORTED |
The adapter emitted an unknown cache layout. | Use the supported OpenNext R2 incremental-cache layout. |
FORGE_OPENNEXT_ISR_MODE_UNSUPPORTED |
KV, D1, tag-cache, or another unsupported ISR mode was requested. | Configure the standard R2 incremental cache. |
FORGE_OPENNEXT_ISR_BINDING_MISMATCH |
Provider R2 identity differs from the frozen Wrangler/binding generation. | Correct the approved target or binding before retrying. |
FORGE_OPENNEXT_ISR_SEED_OVERFLOW |
Trusted ISR ingest crossed its count or byte budget. | Reduce seed output and retry a new release. |
FORGE_OPENNEXT_ISR_SEED_EVIDENCE_INVALID |
Helper/provider receipts do not prove the exact requested mutation. | Reconcile provider state; do not publish the app candidate. |
FORGE_OPENNEXT_ISR_SEED_LEASE_LOST |
Another operation owns the project/Worker mutation fence. | Let the current owner finish, then retry from the durable ledger. |
Forge drains an already scheduled ISR batch before removing its temporary helper, but does not start another batch after any entry fails. Successfully verified entries in that batch remain durable and are skipped by the retry; unverified provider objects may be safely overwritten by exact key and digest.
An OpenNext ISR helper request failed (404) after staging is treated as
bounded provider propagation variance: Forge retries the immutable
version-override request through a 127.75-second fence and then fails closed.
Do not promote the candidate or bypass helper verification when that fence is
exhausted. A connected-provider target lease left behind by a terminated
Worker expires after 90 seconds; an infrastructure retry waits through a
127-second claim fence before failing busy. Forge acquires this mutation lease
after the credential-free build and package plan, so a long OpenNext compile
does not consume or expire the provider-operation fence. Ordinary concurrent
provider operations remain serialized.
FORGE_WRANGLER_INVALID and FORGE_WRANGLER_TOO_LARGE fail before repository
code or provider publication. Connected bundle, WebAssembly, asset, and
provider drift failures also fail before a new Worker Version is created.
Secret values are never a valid diagnostic payload.
If Cloudflare accepted a mutation but Forge lost the response, reconcile using the deterministic artifact identity and provider tag. Do not upload a second candidate until the first mutation's state is known.
Hostname collision, unowned zone, conflicting CNAME, ambiguous path precedence, and unsafe active-domain deletion are terminal policy failures until desired state changes. Provider timeout, certificate pending, DNS pending, and interrupted detach are retryable reconciliation states.
Keep the desired generation and claim while retrying. A failed detach does not prove rollback; only an observed provider detach releases the claim.