Anvil Cloud / Reference
Troubleshooting
anvil cloud check --json and anvil cloud build --json are the primary diagnostic tools. Every failure they report carries a stable code; this page maps the common ones to fixes.
Import policy violations (FORBIDDEN_IMPORT)
Anvil Guard rejects imports that bypass the Cell contract. The diagnostic includes a hint, and the fixes are mechanical:
| Import | Why it is rejected | Fix |
|---|---|---|
fs / node:fs |
Cell code must not touch the host filesystem | Use ctx.files for Cell-owned file storage |
child_process / node:child_process |
Cells cannot spawn processes | Move background work into a declared job |
@aws-sdk/* |
Cells must not call providers directly | Use declared capabilities such as ctx.db or ctx.files |
aws-cdk-lib |
Cell code must not author infrastructure | Provider infrastructure belongs in deployment adapters |
sst |
Same boundary as above | Provider tooling belongs inside deployment adapters |
cdktf, @cdktf/* |
Cell code must not author Terraform/CDKTF infrastructure | Provider infrastructure belongs in deployment adapters |
pulumi, @pulumi/* |
Cell code must not author provider infrastructure | Provider infrastructure belongs in deployment adapters |
If you genuinely need a capability that does not exist yet, that is a platform gap, not something to work around with a direct provider import. Open an issue instead.
Outbound fetch mismatch (OUTBOUND_FETCH_NOT_ALLOWED)
If Cell server code calls fetch("https://host/..."), the host must appear in
capabilities.outboundFetch.allow.
Guard intentionally rejects fetch(url) variables and relative fetch targets in
Cell server code because the allow-list check cannot prove which host will be
called. Local runtime request handlers and workflow steps, plus AWS preview,
also enforce the manifest allow-list while handlers run. Use a literal absolute
http or https URL.
export default app({
capabilities: {
outboundFetch: { allow: ["api.example.test"] },
},
});
Dynamic fetch targets are not fully inspectable in alpha. Prefer a small helper that keeps the external host visible in code, because hiding network access in string plumbing is how tiny demos grow a trench coat.
Build pipeline failures
The builder runs stages in order: config load, import policy, typecheck, server/client bundle, manifest extraction. The first failing stage stops the run, so fix errors top-down.
- Config load fails: the Cell definition could not be evaluated. Run with
--jsonand check the diagnostic; syntax errors and unresolved imports in the app definition surface here. - Typecheck fails: standard TypeScript errors. The builder uses your Cell's
tsconfig; reproduce withtsc --noEmitif you want faster iteration. - Manifest extraction fails: usually a Cell definition that uses dynamic constructs where the builder expects declarative ones. Keep
app,table,query,mutation,endpoint, andjobdeclarations statically analyzable.
Local runtime
- Port already in use: another
anvil cloud devinstance (or anything else) holds the port. Stop it or pass a different port. - Stale behavior after edits: from a workspace checkout, the CLI runs against built package output; rerun
pnpm buildinanvil-cloudafter changing platform packages. Cell code itself is rebuilt by the dev loop. - Database state surprises: the local JSON database adapter persists per project. Inspect it with
anvil cloud dband the local inspector rather than guessing.
AWS preview adapter
- Artifact upload fails: confirm
ANVIL_AWS_ARTIFACT_BUCKETis set and your AWS credentials can write to it. - Stack synthesis or provisioning fails: check
ANVIL_AWS_STACK_PREFIXandANVIL_AWS_DEPLOYMENT_METADATA_TABLE, then read the CloudFormation events for the failed stack; the adapter surfaces the stack name in its output. - Remember the scope: the AWS adapter is a preview. It proves the adapter contract; it is not a production hosting path yet. See Status and limits.
Getting useful output for bug reports
Every CLI command supports --json with stable shapes. When filing an issue at anvil-stack, include:
anvil cloud check --json
anvil cloud build --json
plus the Cell definition if you can share it. JSON output is the contract; screenshots of terminal text are harder to act on.