Hmbown/CodeWhale · error
Managing API keys needs an interactive login. Run…
Error message
Managing API keys needs an interactive login. Run `codewhale login`.
{MACHINE_KEY_ENV} is set, but a Codewhale API key deliberately cannot create, list, or revoke keys — that is what stops a leaked key from minting a replacement for itself. What it means
reject_machine_key_for_management enforces a security invariant: a machine API key (MACHINE_KEY_ENV) can authenticate API calls but can never create, list, or revoke keys. Key management requires an interactive session login; when a machine key is present and no session exists, the CLI bails and states the rationale — preventing a leaked key from minting its own replacement.
Solutions
- Run `codewhale login` in an interactive terminal to establish a session, then retry the management command
- Unset the machine key env var if it is not needed for this command: `unset $MACHINE_KEY_ENV`
- Perform key management from a machine with an interactive session, not from CI
- Use the web console/dashboard to manage keys if CLI login is impossible
Defensive patterns
Strategy: fallback
Validate before calling
// shell: require a session before management commands if [ -n "$MACHINE_KEY_ENV_VALUE" ] && ! codewhale whoami >/dev/null 2>&1; then echo "run 'codewhale login' for key management"; exit 1 fi
Prevention
- Do key management from an interactive login session, never via machine keys only
- Unset machine-key env vars in contexts where you need management operations
- Understand the invariant: machine keys are use-only by design (anti-lateral-minting)
When it happens
Trigger: Running any api-keys management subcommand (create/list/revoke) while MACHINE_KEY_ENV is set and there is no interactive login session, i.e. has_session is false and machine.is_present() is true (crates/cli/src/cloud/machine.rs:875).
Common situations: CI or scripted environments where only the machine key env var is set and someone tries to rotate keys non-interactively; a developer who logged out but still has the env var exported; Docker containers with the key injected as an env var.
Related errors
- refusing non-loopback app-server bind without explicit auth…
- refusing unauthenticated app-server bind on non-loopback…
- This command authenticates with a Codewhale account API…
- API key contains invalid control characters
- API key id must be lowercase hex characters — the part…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/55b2af459dde9b08.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/cloud/machine.rs:875
in the display prefix. Run `codewhale account api-keys list` to see them."
);
}
Ok(id)
}
/// Refuse a management command that would be authenticated by a machine key.
///
/// The server would answer 403 `api_key_route_denied`, but a local refusal is
/// better: it never puts the credential on the wire, and it names the fix.
/// This is the load-bearing rule of the whole design — a stolen key must not
/// be able to bootstrap a successor that outlives the revocation of the key
/// that was stolen — so the CLI states it rather than discovering it.
pub(crate) fn reject_machine_key_for_management(
machine: &MachineKeyEnv,
has_session: bool,
) -> Result<()> {
if machine.is_present() && !has_session {
bail!(
"Managing API keys needs an interactive login. Run `codewhale login`.\n\
{MACHINE_KEY_ENV} is set, but a Codewhale API key deliberately cannot create, list, or \
revoke keys — that is what stops a leaked key from minting a replacement for itself."
);
}
Ok(())
}
/// Run `codewhale account api-keys …` against the interactive session.
pub(crate) fn run_api_keys<T: CloudTransport, W: Write>(
args: ApiKeysArgs,
client: &CloudClient<'_, T>,
machine: &MachineKeyEnv,
provider_secrets: &codewhale_secrets::Secrets,
out: &mut W,
sleeper: &mut dyn FnMut(Duration),
) -> Result<()> {
reject_machine_key_for_management(machine, client.has_session()?)?;View on GitHub (pinned to 73e0f67d83)