openai/codex · error · io::Error

remote control client revoke requires clientId

Error message

remote control client revoke requires clientId

What it means

The second guard in revoke_remote_control_client: after environment_id passes, an empty RemoteControlClientsRevokeParams.client_id is rejected with InvalidInput. The client id is the path segment identifying the enrolled device to delete; without it the request would DELETE the collection path instead of one client.

Source

Thrown at codex-rs/app-server-transport/src/transport/remote_control/clients.rs:136

            .map(RemoteControlClient::try_from)
            .collect::<io::Result<_>>()?,
        next_cursor: response.cursor,
    })
}

pub(super) async fn revoke_remote_control_client(
    remote_control_url: &str,
    auth_manager: &Arc<AuthManager>,
    params: RemoteControlClientsRevokeParams,
) -> io::Result<RemoteControlClientsRevokeResponse> {
    if params.environment_id.is_empty() {
        return Err(io::Error::new(
            ErrorKind::InvalidInput,
            "remote control client revoke requires environmentId",
        ));
    }
    if params.client_id.is_empty() {
        return Err(io::Error::new(
            ErrorKind::InvalidInput,
            "remote control client revoke requires clientId",
        ));
    }
    let mut url = environment_clients_url(remote_control_url, &params.environment_id)?;
    url.path_segments_mut()
        .map_err(|()| {
            io::Error::new(
                ErrorKind::InvalidInput,
                "remote control URL cannot be a base",
            )
        })?
        .push(&params.client_id);
    let response = send_client_management_request(
        auth_manager,
        ClientManagementRequest::Revoke { url: &url },
        "revoke remote control client",
    )

View on GitHub (pinned to 339751715c)

Solutions

  1. Use the exact client_id from the list-clients response entry being revoked
  2. Check for empty string before sending — presence of the field alone (Some("")) is not enough
  3. Fix field mapping in your data layer if ids arrive empty

Example fix

// before
let params = RemoteControlClientsRevokeParams {
    environment_id,
    client_id: String::new(),
};
revoke_remote_control_client(url, &auth_manager, params).await
// Err: remote control client revoke requires clientId

// after
let params = RemoteControlClientsRevokeParams {
    environment_id,
    client_id: client.client_id.clone(),
};
revoke_remote_control_client(url, &auth_manager, params).await  // Ok
Defensive patterns

Strategy: validation

Validate before calling

if (!params.clientId) {
  throw new Error('clientId is required to revoke a remote control client');
}

Type guard

function hasClientId(p: RemoteControlClientsRevokeParams): p is RemoteControlClientsRevokeParams & { clientId: string } {
  return typeof p.clientId === 'string' && p.clientId.length > 0;
}

Prevention

When it happens

Trigger: Invoking revoke with clientId set to an empty string — default-constructed params, a deserialized JSON body missing clientId, or a client record whose id failed to map and coerced to ''.

Common situations: Field-name mismatches during serialization (clientID vs clientId); acting on a client entry whose id was null; UI detail panes that never thread the id through.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/e851df4e793a004d. Report an issue: GitHub.