Troubleshooting
Symptom, cause, check, fix. The failures this SDK actually produces.
Every entry is a symptom you can see, the cause behind it, and the check that tells them apart. If none of these fit, get in touch with the request id.
Nothing renders after open()
The copilot draws nothing and no error appears anywhere.
- The key is not a publishable key.
initrefuses anything that does not start withrd_pk_(ornc_pk_, a key made before the rename), disables the copilot for the run and asserts in debug. CheckRendel.isInitialized. - The key is still the placeholder.
rd_pk_test_...from an example is not a key. Copy your app's own from the console: Settings → API keys, Copy beside Test. - The copilot is switched off.
RendelConfig(enabled: false)in code, or a kill switch published from the console, both makeRendelLauncherdraw nothing andopen()return without presenting.Rendel.isEnabledtells you which state you are in. initnever ran, or ran after the widget built. It is aFuture; await it inmainbeforerunApp.
Install fails
rendel is in private pilot and is not on pub.dev yet. It installs from a git reference; Install the SDK has the exact block. It needs Dart 3.5 and Flutter 3.24 or newer; older toolchains fail version solving rather than compilation.
The copilot answers but never calls my action
The model replies in prose about something your action was registered to do.
- The manifest never synced. Registering an action queues a sync; if the device was offline at launch it fails, and
open()retries it. Until a sync lands, every turn ends inmanifest_unknown. Watch formanifest_sync_failedin youronLogsink. - The name was rejected. Action names are
snake_case. The SDK asserts this at the line that declares the action; if you built the manifest by hand, the server rejects the whole document over one bad name. - The action is disabled. Check the Actions page in the console. A disabled action is not offered to the model at all, and the change takes effect on the next turn for every version of your app.
- The description is doing no work. The model chooses from names, descriptions and parameter types. "Fetch the delivery status of an order by id" beats "order helper".
The confirmation card never appears, or stops working
- The risk level is
read. Onlywriteanddestructiveproduce a card. Read actions run immediately, by design. - It expired. A card is answerable for ten minutes, with a grace period for a handler that was already running. After that the model is told the user never answered.
- Two actions in one turn. A confirmable action must be the only action call in a message. The server refuses the pair and asks the model to try again; you may see a turn take a beat longer.
Knowledge answers ignore my sources
- Semantic retrieval is not switched on for your app yet. Until it is, the copilot answers from your actions and app state, and the console says so on the Knowledge page. Ask us to enable it.
- The source is not
ready. Sources are chunked on save and indexed when retrieval is enabled. - The console's test box is not the live path. It matches text; retrieval matches meaning. A passing test there does not prove a live answer will be grounded.
Theming does not apply
- The palette was refused.
fromTokensaudits contrast and discards a whole published palette it cannot make legible, rather than applying half of it. The reason is reported throughonLog. - The console published over you. A published appearance layers over your code config. Set
RendelConfig(remoteConfig: false)to pin the build to exactly what your Dart says, and see whether the look changes. - You themed the sheet but not the launcher. Both read the same theme now; if the launcher looks wrong and the thread looks right, you are on an older SDK.
The stream drops, or the thread hangs
- A turn that goes quiet is abandoned after
RendelConfig.streamIdleTimeout, 45 seconds by default, and offers a retry. - A retry is safe. It resends the same
turn_id, so the server recognises it and neither stores the message twice nor bills for it twice. - A retry that cannot help is not offered. At a cap or a rate limit the error is marked non-retryable and no Retry button is drawn.
Everything fails at once
- Check the key's environment. A test key is sandbox: never billed, and it receives the draft console configuration. A live key receives the published one.
- Check the app is not suspended. A suspended app answers every call with a quota error.
- Check your API host.
RendelConfig(apiBaseUrl:)must point at a host that resolves. The default is correct unless you overrode it.
Getting help
Send the request id. It is on turn.start, on the X-Request-Id response header, in every onLog record, and in our server logs. With it, a problem resolves to one turn: what was asked, what was rendered, which actions ran and what the server was doing. You can do that lookup yourself: paste it into the search on Conversations in the console. See Errors and Support.