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

  1. Upgrade the astrid CLI to the version matching the server's invite API — the response shape likely changed on the server side.
  2. 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.
  3. Verify you're pointing at the correct API endpoint/environment (prod vs staging) and API version path.
  4. 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

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/413b3066da6eb464. Report an issue: GitHub.