Troubleshooting

Diagnose common Restish setup, request, auth, output, pagination, spec, TLS, and plugin problems.

Use this page when the command ran but the result was surprising, or when the command did not run because shell, config, auth, TLS, or plugin setup got in the way.

The Shell Rewrites My URL Or Filter

Symptom: A command with ?, &, [0], [], or * fails before Restish sends a request.

Likely cause: Your shell expanded the characters.

How to confirm: Quote the URL or filter and retry.

Fix:

restish shell setup zsh
restish 'api.rest.sh/images?format=jpeg&limit=1'
restish api.rest.sh/images --rsh-no-paginate -f 'body[0].self'

Prevention: Quote complex arguments in scripts and run restish shell setup <shell> for interactive use.

Related docs: Shell Setup, Shell Command, Query Syntax.

I Expected JSON But Got Auto Output

Symptom: stdout is human-friendly instead of the exact JSON shape you want.

Likely cause: The default output format is auto.

How to confirm: Run with an explicit format.

Fix:

restish api.rest.sh/images -o json

Prevention: Use -o json in scripts and redirects when the format matters. Add --rsh-print=b when the script needs compact rendered JSON.

Related docs: Output, Output Defaults.

I Redirected Output And Got The Server’s Format

Symptom: A redirected response is CBOR, YAML, text, or another server format instead of JSON.

Likely cause: Redirected unfiltered output saves response body bytes. This can happen when the endpoint only returns that format, a profile or command set an Accept header, or the server ignored Restish’s JSON-first default negotiation.

How to confirm: Run with an explicit format.

Fix:

restish api.rest.sh/formats/cbor -o json > response.json

Prevention: Use -o json when a file or script needs JSON. Omit -o when you want to save the response body unchanged. Add --rsh-print=b when compact rendered JSON is preferable to the pretty default.

Related docs: Output Defaults, Save a Response Unchanged.

Config Directory Cannot Be Determined

Symptom: Restish says it cannot determine the config directory.

Likely cause: The environment has no explicit config path and no usable home or platform config directory.

Fix: Set one of these before running Restish:

export RSH_CONFIG_DIR="$HOME/.config/restish"
export RSH_CACHE_DIR="$HOME/.cache/restish"

For project-local config, use .restish.json plus restish config trust, or select a complete config explicitly with RSH_CONFIG=/absolute/path/.restish.json or --rsh-config /absolute/path/.restish.json.

Related docs: Config, Environment Variables.

v1 Migration Backup Already Exists

Symptom: A v1-to-v2 migration mentions a .bak.v1 backup, or you are recovering after an interrupted migration.

Likely cause: Restish found a prior v1 backup directory.

Fix: Run Restish again. Matching backups are reused; different existing backups are preserved and a numbered backup such as .bak.v1.2 is created. After migration, the old apis.json and config.json are removed from the legacy location so they are not imported again.

Related docs: Upgrade From v1.

Content Negotiation Returned A Different Format

Symptom: The server returns CBOR, YAML, or another structured media type instead of JSON.

Likely cause: Restish sends an Accept header listing all registered content types with quality values. The default header prefers JSON and other text-friendly structured formats, but servers can still choose another supported response type or ignore client preferences.

How to confirm: Inspect the request with /headers or verbose mode.

Fix:

restish -H 'Accept: application/json' api.rest.sh/formats/json
restish -v api.rest.sh/headers

Prevention: Set an Accept header in a profile for APIs that negotiate aggressively.

Related docs: Content Types, Profiles.

Auth Fails

Symptom: The API returns 401 or 403.

Likely cause: Missing credential, wrong profile, expired token, or auth on a public operation where it should have been suppressed.

How to confirm: Test against the safe auth fixtures.

Fix:

restish -H 'Authorization: Bearer docs-token' api.rest.sh/auth/bearer
restish api auth inspect example
restish api auth inspect example --credential basicAuth
restish api auth get example basicAuth
restish -v -p token api.rest.sh/auth/bearer

For generated OpenAPI commands, errors mentioning missing credential bindings mean the selected profile does not have a credentials.<id> entry for that operation. Errors mentioning missing requirement values mean the binding’s satisfies list does not include the required scope or role.

For OAuth-backed requests, Restish automatically forces fresh auth and retries once after a 401 Unauthorized. If you still see 401 after that retry, inspect the active profile, confirm scopes/roles, or clear cached auth so the next request performs a fresh flow.

Prevention: Put auth in profiles and keep public/private operation security accurate in OpenAPI.

Related docs: Authentication, Profiles.

Generated Commands Are Missing

Symptom: restish myapi --help does not show expected operations.

Likely cause: Spec discovery failed, the cached spec is stale, operation names changed, or operations are hidden/ignored.

How to confirm:

restish api inspect myapi
restish api sync myapi
restish myapi --help

Fix: Set spec_url, sync the API, or update the OpenAPI document.

Prevention: Publish /openapi.json or service-description links and keep operation IDs stable.

Related docs: API Setup and Discovery, OpenAPI Reference.

Config Permissions Are Rejected

Symptom: Restish exits with a message that restish.json is group/world-readable.

Likely cause: The config file permissions allow other local users to read profiles, headers, or auth settings.

How to confirm:

ls -l ~/.config/restish/restish.json

Fix: Restrict the file to your user.

chmod 600 ~/.config/restish/restish.json

Prevention: Create config through Restish commands when possible; they write private files by default.

Related docs: Config, Authentication.

Pagination Changed My Output Shape

Symptom: A paginated endpoint behaves differently from a one-page endpoint.

Likely cause: Restish follows next links and may stream items unless a document format or collect mode requires buffering.

How to confirm:

restish api.rest.sh/images --rsh-no-paginate -f links.next
restish api.rest.sh/images --rsh-collect -f '.body | length'

Fix: Use --rsh-no-paginate, --rsh-max-pages, --rsh-max-items, or --rsh-collect explicitly.

Prevention: Choose document output for whole results and record output for item streams.

Related docs: Pagination, Output.

Live Stream Output Never Finishes

Symptom: A stream keeps running or -o json is not useful.

Likely cause: SSE and NDJSON streams may be unbounded, while JSON is a document format.

How to confirm: Add an item cap or a timeout.

Fix:

restish api.rest.sh/events --rsh-max-items 3 -o ndjson
restish api.rest.sh/events --rsh-max-items 3 -f body.data.message -o lines
restish api.rest.sh/events --rsh-collect --rsh-max-items 3 -o json

Prevention: Use --rsh-max-items for fixed samples and --rsh-timeout for time-bounded stream checks. Use -o ndjson for record-by-record JSON output, or pair --rsh-collect with a finite --rsh-max-items when you explicitly want one JSON document. For SSE, parsed event payload fields live under body.data; for NDJSON records, fields live directly under body.

Related docs: Streaming, Output Formats.

The Body Is Hidden Because Status Failed

Symptom: A non-2xx response fails the command and interrupts a script.

Likely cause: HTTP status families map to exit codes.

How to confirm: Use a status fixture.

Fix:

restish api.rest.sh/status/404 --rsh-ignore-status-code
restish api.rest.sh/problem --rsh-ignore-status-code

Prevention: Use --rsh-ignore-status-code when error bodies are expected data.

Related docs: Command Behavior.

Cache Looks Stale

Symptom: A response does not reflect the latest server state.

Likely cause: A cacheable response was served from the local HTTP cache.

How to confirm: Run with verbose mode or bypass cache.

Fix:

restish api.rest.sh/cache --rsh-no-cache
restish cache info
restish cache clear

Prevention: Use --rsh-no-cache while debugging server state.

Related docs: Retries and Caching, Cache Command.

TLS Or mTLS Fails

Symptom: Certificate verification, custom CA, client certificate, or TLS signer setup fails.

Likely cause: Unknown CA, wrong client cert/key pair, missing hardware token, or plugin configuration error.

How to confirm:

restish cert api.rest.sh
restish cert --rsh-ca-cert ./corp-ca.pem https://service.internal.test

Replace service.internal.test with a reachable internal service before running the custom-CA example.

Fix: Use the correct CA, client certificate, key, or TLS signer parameters. Avoid --rsh-insecure except for short debugging.

Prevention: Store TLS settings in profiles for repeated use.

Related docs: TLS, Utility Commands, TLS Signer Plugins.

Plugins Are Not Discovered Or Fail

Symptom: A plugin command or output format is unavailable, or a plugin exits with protocol errors.

Likely cause: The plugin is not installed, not executable, not in a discovered location, or is using an incompatible protocol.

How to confirm:

restish plugin list
restish plugin debug ./path/to/plugin

Fix: Install the plugin, fix permissions, rebuild for v2, or inspect decoded messages with plugin debug.

Prevention: Keep operator docs separate from author protocol docs and verify plugin discovery after installation.

Related docs: Install and Use Plugins, Plugin Command, Plugin Messages.

A CRUD Example Changed Shared State

Symptom: /items examples produce data different from the docs.

Likely cause: The CRUD fixture is resettable but stateful enough for examples to interact.

How to confirm:

restish api.rest.sh/items

Fix: Use unique IDs for create/update/delete examples, such as docs-$USER or a timestamp.

Prevention: Recipes that mutate /items should create their own item and clean it up.

Related docs: Create, Patch, and Delete an Item.