← Files TemporalARCHIVED FILE
skills/temporal-cloud-setup/references/failure-handling.md
12.5 KB · Oct 2, 2026 · 00:08 UTC
# Failure Handling — `error_code` → remediation map Read this when a `scripts/provision.sh` subcommand returns `status=error`. SKILL.md's Failure Handling section points here; the Steps spine's "On-error" column is the index of which codes each step can emit. Stop and surface the problem (don't silently retry destructive or auth steps), staying in the calm output style — report the problem and fix plainly, without exposing reasoning. The script ops fail loudly with `status=error` + an `error_code`; **fix the cause the code names and re-run the same op — never improvise an alternate command, switch output formats, or poll.** Map the codes: - **`brew-missing` / `manual-install`** (install-cli) → relay the script's message: install Homebrew from https://brew.sh, or download `temporal-cloud` from the releases page and put it on `PATH`. Do **not** auto-install Homebrew. Re-run install-cli. - **`login-failed` / `not-authenticated`** (login, or any later op) → the browser sign-in didn't complete or the session expired. Ask the user to finish/redo the browser login, then re-run the op (create-namespace / create-key re-check auth themselves). - **`cloud-unreachable`** (the post-login region pulse) → the Cloud API can't be reached. **This is a network / sandbox problem, NOT an auth problem — do NOT re-run `login`.** The classic case: `login` and `whoami` both succeed (they use the browser loopback / a cached token and run **offline**), yet the gRPC Cloud API is blocked by a sandbox or firewall, so the region pulse comes back empty. Tell the user to run the skill from an environment with **outbound internet and gRPC egress to the Temporal Cloud API** (`*.tmprl.cloud`); e.g. Codex's default sandbox blocks this. Re-running sign-in will only loop — the fix is connectivity. Once network is fixed, re-run the failed step. - **`config-dir-unwritable`** (preflight) → the Temporal config directory can't be written. Fix its permissions, or set `TEMPORAL_CONFIG_FILE` to a writable path, then re-run. Caught **up front**, before any billable key is minted (writing `temporal.toml` is our op, so nothing else surfaces this). - **`regions-empty`** (legacy code — no longer emitted) → the region step now maps an empty region list onto `cloud-unreachable` (see above), since an empty list means the Cloud API is unreachable, not that auth is missing. If you ever see `regions-empty` from an older build, treat it exactly as `cloud-unreachable`: check network/sandbox, not auth. - **`create-rejected`** (start-namespace) → the namespace create was rejected on submit, usually region or name format; re-list regions, have the user pick an exact provider-prefixed value, then re-run `start-namespace`. Attribute this as a **namespace** failure, never as a downstream key error. - **`namespace-timeout`** (await-namespace) → the namespace **appeared** (ACTIVATING) but didn't reach **ACTIVE** within the bound (`NS_AWAIT_MAX_SECS`, default 600s). It's provisioning lag, not a misconfig: re-run `await-namespace` (it resumes polling the exact `namespace list --name` filter until the namespace is ACTIVE); raise the bound with `NS_AWAIT_MAX_SECS=N` if needed. Don't switch to `namespace get`/other formats. (Waiting for ACTIVE here is what keeps `create-key`/`await-auth` from connecting to an endpoint that isn't serving yet — the cause of a "no children to pick from" stall.) - **`namespace-not-provisioning`** (await-namespace / provision-and-scaffold) → the create was accepted but the namespace **never appeared** in the list within the phantom-grace window (`NS_PHANTOM_GRACE_SECS`, default 75s) — i.e. it's not provisioning at all, vs. just slow. Almost always an **unavailable region** (e.g. `azure-centralus`, whose provider reads `UNKNOWN` — see the region step's `unsupported_regions`). Don't re-run `await-namespace` on the same name; **re-run `start-namespace` with an AWS/GCP region**. - **`handle-not-found`** (provision-and-scaffold) → the namespace was created but didn't reach **ACTIVE** within the retry bound (still provisioning). Re-run `provision-and-scaffold` or `await-namespace` to resume the wait. **Never** decode the API-key token or hunt the filesystem/config for the account-id — the exact `namespace list --name` filter is the source. - **`clone-failed` / `unknown-sdk`** (scaffold) → the sample clone failed (network/repo) or the SDK has no repo mapping; confirm the SDK + connectivity, then re-run `scaffold`. (Independent of the namespace, which is already provisioning.) - **`manager-not-found`** (scaffold / install-deps) → the chosen package manager isn't installed on this machine. Offer an **available** manager from the latest `detect-tools` `managers` list, or ask the user to install the missing one, then re-run with that `--manager`. Caught **before** the clone, so nothing was set up. - **`unsupported-manager`** (scaffold / install-deps) → that manager isn't valid for this SDK's sample (e.g. `poetry` for Python, whose sample ships no `pyproject.toml`). Pick one of the supported managers named in the error / `detect-tools` and re-run. - **`version-too-old`** (detect-tools `discrepancies`, **advisory**) → not a hard error and never blocks the run. Relay the remediation (upgrade the tool to the noted minimum) but you may proceed — the sample usually still works on the older version. - **`no-json-parser`** (create-key) → install `jq` or `python3` (needed to capture the token safely), then re-run create-key. - **`key-empty` / `key-create-failed`** (create-key) → almost always an expired login (not an output-format problem); the script re-checks `whoami` — redo the browser login if prompted, then re-run create-key once. - **`key-limit-reached`** (create-key) → the account is at its **API-key cap**, so the mint was rejected at create time (not an auth or output problem — every run mints a fresh key, so a repeat tester accumulates them). Delete stale keys, then re-run create-key: list with `temporal cloud apikey list` and remove old `money-transfer-cloud-setup-*` keys with `temporal cloud apikey delete --key-id <id>`. Don't re-run login or switch output formats. - **`config-write-failed`** (create-key) → the profile couldn't be written to `temporal.toml` (read-only dir or full disk); the key was minted but not saved. Fix directory permissions / free disk, then re-run create-key (it mints a fresh key and writes a clean profile). - **API key lost** (only shown once) → re-run create-key to mint a fresh one (it rewrites the profile); don't try to recover the old value. - **`temporal.toml` unparseable / duplicate `[profile.cloud-setup]` blocks** (e.g. from earlier partial runs) → run `scripts/provision.sh repair-config` (strips every `cloud-setup` block via awk, keeps `[profile.default]`, never reads the file into context), then re-run `create-key` to write one fresh profile. **Do not hand-edit, `cat`, or `awk` the file yourself** (the read-only-script rule and the secret carve-out) — `create-key` also strips any existing/duplicate `cloud-setup` blocks before writing, so it self-heals too. - **`worker-unauthorized`** (run-workflow) → the Worker hit an auth error before it could poll — the just-minted key isn't accepted yet. Re-run `await-auth` (wait for `auth_ready=true`), then re-run `run-workflow`. Do **not** switch endpoints, re-mint the key, or edit the profile (it's readiness, not config). - **`precompile-failed`** (run-workflow) → the Maven/dotnet build step failed before the Worker started. Java and .NET are pre-compiled once so the timing windows cover only Temporal operations. Check the output above; usually a missing Java/Maven/.NET SDK installation or a network issue fetching dependencies on the first build. - **`worker-not-polling`** (run-workflow) → the Worker started but never registered as a poller within the bound (`WORKER_READY_MAX_SECS`, default 120s). Usually deps weren't installed or the Worker process crashed early. Confirm `scaffold` finished and `--dir` is the real `repo_path`, then re-run; raise the bound with `WORKER_READY_MAX_SECS=N` if needed. The script prints the Worker log tail to help. - **`worker-start-failed`** (run-workflow) → the Worker process exited before polling (missing deps/venv, wrong dir, or a sample-app error in the log tail). Confirm deps installed and `--dir` is correct, then re-run. - **`workflow-failed`** (run-workflow) → the starter exited non-zero / the Workflow didn't reach `COMPLETED`. Read the printed log tail: if it's an auth error, run `await-auth` and retry; otherwise surface the sample-app error. (Expected `FAILED` for the manual `DEMO_FAILURE=permanent` variant is **not** run through `run-workflow`.) - **`workflow-not-submitted`** (run-workflow) → the starter exited **0 but never submitted a Workflow** within the settle window (`NOWF_SETTLE_SECS`, default 15s). Some sample clients catch their own connect/start error and still exit 0 (the .NET starter does this), so a clean exit code can hide a failed start. Read the printed log tail — it's almost always an auth/connection error: run `await-auth` (wait for `auth_ready=true`) and re-run `run-workflow`; if the profile points at a namespace that isn't ACTIVE, re-check `await-namespace` first. - **`workflow-timeout`** (run-workflow) → the starter didn't finish within `--max-secs` (default 180s). The Cloud workflow is automatically terminated on timeout so it doesn't stay Running with no worker. If it still fires, raise with `--max-secs N` and re-run. - **`Request unauthorized` / `Unavailable` on the first connect (right after setup)** → almost always **post-provision readiness**, not a misconfig: the just-created namespace + key need a moment to become connectable, and the parallel flow shortens that gap. **Wait ~10–15s and retry the connect, up to ~3 times.** Do **not** switch the address to a regional endpoint, re-mint the key, or rewrite the profile. The namespace endpoint (`<handle>.tmprl.cloud:7233`) is the correct, Temporal-recommended endpoint for API keys (temporalio/documentation#4733); regional is **not** the fix. If it still fails after retries, that's a Temporal Cloud issue to escalate — not a reason to change the skill's endpoint. - **`key-expired`** (await-auth) → the poll came back with a **high-confidence permanent key failure** — a permanent qualifier (**expired / invalid / revoked / not found / disabled**) anchored to **jwt / api key / token** context (the real prerelease message is the Envoy JWT-filter desc `Unauthenticated desc = Jwt is expired`; see `references/unified-cli.md`), so await-auth **fast-failed** instead of spinning the full bound; the key won't clear by waiting. The classic cause: keys auto-expire in ~25h, so a next-day re-test polls a dead key. Fix: re-run `create-key` to mint a fresh key (it overwrites the `[profile.cloud-setup]` block). If you're at the API-key cap, delete stale keys first (see `key-limit-reached`), then re-run `create-key`. The message carries a **redacted** CLI stderr tail for context. (A bare, unqualified `Request unauthorized` during propagation is treated as **transient** — see below — so this never wrong-fast-fails a key that just needs a moment.) Don't switch endpoints or edit the profile. - **`auth-timeout`** (await-auth) → the new API key still isn't accepted after the bound (`AUTH_READY_MAX_SECS`, default 90s), and the failures were **transient** — the usual post-provision `Request unauthorized` propagation, not the qualified permanent text that triggers `key-expired`. Wait longer and re-run `await-auth`; if it never clears, re-run `create-key` to mint a fresh key. The message now appends the **last captured, redacted** CLI stderr line so the timeout is diagnosable instead of blank — read it before deciding. Each poll is itself bounded by a per-call timeout (`AUTH_POLL_CALL_TIMEOUT`, default 15s) so a single wedged call can't hang the loop, and the ~`AUTH_READY_MAX_SECS` budget is counted in real wall-clock. Don't switch endpoints or edit the profile. - **TLS / auth errors at connect** → confirm the profile's `[profile.cloud-setup.tls]` has `disabled = false` (TLS on), the address is the **namespace endpoint** (`<handle>.tmprl.cloud:7233`), and the `api_key` is set; re-run `verify-config`. (`create-key` now writes `disabled = false` explicitly.) - **`temporal cloud …` commands suddenly fail auth (after deleting/expiring the key)** → a profile carrying an `api_key` overrides the login session. Remove the `[profile.cloud-setup]` block, or pass `--disable-config-file`. The setup always lives in the **named** `cloud-setup` profile (never `default`), so management commands keep using the login session.
SHA-256: e2adbfc5136e38014b3710fbcca6270101804fff2dacff84ccac9cfa404a5454