astrid-runtime/astrid · error
MCP attach registration is missing hook_token
Error message
MCP attach registration is missing hook_token
What it means
validate_registration requires every attach registration to carry a hook_token, a shared secret minted by the gateway that authenticates subsequent requests. A missing (empty/whitespace-only) hook_token is rejected before any uplink selection or workspace validation happens. This prevents unauthenticated attaches from proceeding further into gateway state.
Source
Thrown at crates/astrid-cli/src/commands/mcp/gateway.rs:934
Ok(request)
}
fn validate_registration(registration: &AttachRegistration) -> Result<()> {
if registration.version != ATTACH_REGISTRATION_VERSION {
anyhow::bail!(
"unsupported MCP attach registration version {}",
registration.version
);
}
super::lifecycle::resolve_principal(Some(®istration.principal))?;
if registration.host.trim().is_empty() {
anyhow::bail!("MCP attach registration has an empty host");
}
if registration.host_session_id.trim().is_empty() {
anyhow::bail!("MCP attach registration has an empty host_session_id");
}
if registration.hook_token.trim().is_empty() {
anyhow::bail!("MCP attach registration is missing hook_token");
}
validate_workspace(®istration.workspace_abs)?;
Ok(())
}
fn authenticate_registration(
registration: &AttachRegistration,
state: &GatewayState,
) -> Result<astrid_core::PrincipalId> {
let principal = super::lifecycle::resolve_principal(Some(®istration.principal))?;
if principal != state.principal {
anyhow::bail!(
"MCP attach registration principal '{}' is not the authenticated gateway principal '{}'",
principal,
state.principal
);
}
if registration.hook_token != state.hook_token {View on GitHub (pinned to affd8760f4)
Solutions
- Populate hook_token from the gateway's minted token (startup lease / readiness record) before attaching
- Verify the readiness file was read successfully and its hook_token field copied into the registration
- Regenerate/restart the gateway if the token was lost and re-read the readiness metadata
- Log the registration payload (minus secrets) to confirm which field is empty
Example fix
// before hook_token: String::new(), // after hook_token: ready_record.hook_token.clone(),
Defensive patterns
Strategy: validation
Validate before calling
if reg.hook_token.trim().is_empty() { return Err("hook_token is required: read the gateway readiness record first"); } Type guard
fn has_hook_token(reg: &AttachRegistration) -> bool { !reg.hook_token.trim().is_empty() } Prevention
- Read the readiness record and clone its hook_token into every registration
- Never construct AttachRegistration with String::new() defaults
- Rotate client code when gateway token format changes
When it happens
Trigger: Sending an AttachRegistration via the MCP attach request path with hook_token empty or absent; creating the registration struct manually without copying the token from the gateway startup lease/ready record.
Common situations: Client never read the gateway readiness metadata containing hook_token; placeholder left empty in a config file; token field dropped during payload serialization; tests constructing AttachRegistration by hand.
Related errors
- MCP gateway control authority is incomplete
- MCP attach host session key is empty
- MCP attach host is empty
- MCP attach registration has an empty host
- MCP attach registration has an empty host_session_id
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b831c188e72fd307.
Report an issue: GitHub.