astrid-runtime/astrid · error
unexpected response shape: {other:?}
Error message
unexpected response shape: {other:?} What it means
run_issue in invite.rs matches on the response returned by the invite-issuing API and only recognizes the expected success variants (e.g. one carrying expires_at_epoch). Any other response shape — an error payload, a schema change, or a wrapper object — falls into the catch-all `other` arm and bails with a debug dump of the value. This signals that the server returned something the CLI does not understand, so it refuses to guess.
Source
Thrown at crates/astrid-cli/src/commands/invite.rs:137
AdminResponseBody::Invite(issued) => {
if args.raw {
println!("{}", issued.token);
} else {
println!(
"{} {} (group: {}, uses: {}, metadata: {})",
Theme::success("issued"),
issued.token.bold(),
issued.group,
issued.remaining_uses,
issued.metadata.as_deref().unwrap_or("-"),
);
if let Some(exp) = issued.expires_at_epoch {
println!("expires at unix epoch {exp}");
}
}
Ok(ExitCode::SUCCESS)
},
other => anyhow::bail!("unexpected response shape: {other:?}"),
}
}
async fn run_redeem(args: RedeemArgs) -> Result<ExitCode> {
// Resolve the public key source: either an explicit `--public-key`
// hex string or a local `--keypair` reference. Exactly one is
// required (clap enforces mutual exclusion; this enforces presence).
let (public_key_hex, keypair_name) = match (args.public_key, args.keypair) {
(Some(hex), None) => (hex, None),
(None, Some(name)) => {
let hex = crate::commands::keypair::load_public_key_hex(&name)
.with_context(|| format!("load public key for --keypair {name:?}"))?;
(hex, Some(name))
},
(None, None) => anyhow::bail!(
"redeem requires either --public-key <hex> or --keypair <name>. \
Generate one with `astrid keypair generate`."
),View on GitHub (pinned to affd8760f4)
Solutions
- Upgrade the astrid CLI to the version matching the server's invite API — the response shape likely changed on the server side.
- Check the server response directly (curl the invite endpoint) and compare with the shape the CLI expects; report the {other:?} dump in a bug report if it looks valid.
- Verify you're pointing at the correct API endpoint/environment (prod vs staging) and API version path.
- If the server is emitting an error, fix the underlying request (auth token, permissions) so the expected success variant is returned.
Example fix
// before
$ astrid --server https://staging.api.example.com invite issue --org acme
unexpected response shape: Error { code: 403, message: "forbidden" }
// after (correct environment/updated CLI)
$ astrid --server https://api.example.com invite issue --org acme
issued invite, expires at unix epoch 1760000000 Defensive patterns
Strategy: type-guard
Validate before calling
// validate the expected shape before printing
if !matches!(resp, InviteResponse::Issued(_)) {
eprintln!("invite API returned a non-issued response; check CLI/server versions");
} Type guard
fn is_issued(resp: &InviteResponse) -> bool {
matches!(resp, InviteResponse::Issued(_))
} Try / catch
match run_issue(args).await {
Ok(code) => code,
Err(e) if e.to_string().starts_with("unexpected response shape") => {
eprintln!("Server response not understood by this CLI version; upgrade astrid-cli or verify the endpoint, then retry.");
ExitCode::FAILURE
}
Err(e) => { eprintln!("{e:#}"); ExitCode::FAILURE }
} Prevention
- Keep the CLI version in lockstep with the invite service API version
- Pin the API endpoint/environment explicitly rather than relying on defaults
- Log the full {other:?} payload when it occurs and file it with a bug report
- Add a contract test against the live API shape when upgrading either side
When it happens
Trigger: `astrid invite issue` (run -> run_issue) receives an API response that deserialized into a variant other than the expected Issued shape — e.g. server returned an error object, a paginated envelope, or a new field-layout variant after an API version bump.
Common situations: Server/client version skew: the CLI talks to a newer or older invite service whose response JSON shape changed; hitting the wrong endpoint or environment (staging returning an error envelope); proxy or gateway returning an HTML/JSON error body that still deserializes; API deprecation changing the response enum.
Related errors
- failed to fetch {name} from {url} (HTTP {})
- unexpected response shape: {other:?}
- unexpected daemon metadata response: {other:?}
- invalid key: must not be empty
- --scope requires the capsule manifest to declare '{key}' as
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/413b3066da6eb464.
Report an issue: GitHub.