BigPizzaV3/CodexPlusPlus · error · anyhow::Error

registration type must be register

Error message

registration type must be register

What it means

After JSON-parsing the first WebSocket message, the relay validates that RegisterMessage.message_type equals the literal "register". Any other message_type value bails, because the relay only accepts registration frames on a fresh connection.

Solutions

  1. Set message_type to exactly "register" in the first message
  2. Update the client library to the current relay protocol version
  3. Send only the registration frame first; send other messages after registration succeeds

Example fix

// before
{ "message_type": "Register", "room": "r1", "token": "t", "role": "client" }
// after
{ "message_type": "register", "room": "r1", "token": "t", "role": "client" }
Defensive patterns

Strategy: validation

Validate before calling

if (reg.message_type !== 'register') throw new Error('message_type must be "register"');

Type guard

const isRegisterMessage = (m: unknown): m is RegisterMessage => typeof m === 'object' && m !== null && (m as any).message_type === 'register';

Try / catch

ws.onclose = (e) => { if (String(e.reason).includes('registration type')) fixMessageTypeAndReconnect(); };

Prevention

When it happens

Trigger: Sending a first frame that is valid JSON but whose message_type field is not "register" (e.g. "Register", "reg", or a data/chat message) during handle_websocket_connection -> parse_registration (main.rs ~365).

Common situations: Client sends a chat/data message before registering; case mismatch "Register" vs "register"; outdated client using an older protocol message_type value.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/0b90c76bd046a86b. Report an issue: GitHub.

Appendix: source

Thrown at apps/codex-plus-mobile-relay/src/main.rs:365

    );
    stream.write_all(response.as_bytes()).await?;
    stream.write_all(&body).await?;
    stream.shutdown().await?;
    Ok(())
}

fn parse_registration(message: Message) -> anyhow::Result<Registration> {
    let text = match message {
        Message::Text(text) => text.to_string(),
        Message::Binary(bytes) => {
            String::from_utf8(bytes.to_vec()).context("binary registration must be utf-8 json")?
        }
        _ => bail!("first message must be registration json"),
    };
    let registration: RegisterMessage =
        serde_json::from_str(&text).context("registration is not valid json")?;
    if registration.message_type != "register" {
        bail!("registration type must be register");
    }
    if registration.room.trim().is_empty() {
        bail!("room is required");
    }
    if registration.token.trim().is_empty() {
        bail!("token is required");
    }
    let role = Role::from_str(&registration.role).context("role must be host or client")?;
    Ok(Registration {
        role,
        room: registration.room,
        token: registration.token,
    })
}

fn registration_from_uri(path: &str, query: Option<&str>) -> Option<Registration> {
    let query = query?;
    let role = match path {

View on GitHub (pinned to b1ed92e5e4)