schollz/croc · error · Error
Peer message did not include a type
Error message
Peer message did not include a type
What it means
decodeMessage() decrypts, decompresses, and JSON-parses a peer message, then requires the parsed wire object to carry a truthy 't' (type) field. Every well-formed croc protocol message must be tagged with a type so the receiver can dispatch it. If the JSON decodes but 't' is absent, null, or empty, the message is considered malformed and rejected.
Source
Thrown at web/src/protocol/codec.ts:45
if (message.m) wire.m = message.m;
if (message.b?.byteLength) wire.b = bytesToBase64(message.b);
if (message.b2?.byteLength) wire.b2 = bytesToBase64(message.b2);
if (message.n) wire.n = message.n;
let bytes = await wasm.compress(textEncoder.encode(JSON.stringify(wire)));
if (key) bytes = await wasm.encrypt(bytes, key);
return bytes;
}
export async function decodeMessage(
wasm: CrocWasm,
payload: Uint8Array,
key?: Uint8Array,
) {
let bytes = payload;
if (key) bytes = await wasm.decrypt(bytes, key);
bytes = await wasm.decompress(bytes, MAX_FRAME_SIZE);
const wire = JSON.parse(textDecoder.decode(bytes)) as WireMessage;
if (!wire.t) throw new Error("Peer message did not include a type");
return {
t: wire.t,
v: wire.v,
m: wire.m,
b: wire.b ? base64ToBytes(wire.b) : undefined,
b2: wire.b2 ? base64ToBytes(wire.b2) : undefined,
n: wire.n,
} satisfies CrocMessage;
}
View on GitHub (pinned to e25f1bdc04)
Solutions
- Check what the peer actually sent: log the decoded JSON (before the throw) and confirm the message shape; well-formed croc messages always include a type such as 'pake', 'offer', or chunk data.
- Verify both peers run compatible protocol versions; a peer omitting 't' is violating the wire contract and should be updated.
- In tests, always include the 't' field when constructing WireMessage fixtures (e.g. { t: "transfer", v: 1 }).
- If you control the sender, add the type tag before serializing/encrypting with encodeMessage.
Example fix
// before (test fixture / peer)
const wire = { v: 1, b: base64 }; // missing type
// after
const wire = { t: "transfer", v: 1, b: base64 }; Defensive patterns
Strategy: try-catch
Validate before calling
function looksLikeTypedWire(json: string): boolean {
try {
const parsed = JSON.parse(json);
return typeof parsed?.t === "string" && parsed.t.length > 0;
} catch {
return false;
}
} Type guard
function isWireMessage(value: unknown): value is { t: string } {
return typeof value === "object" && value !== null &&
typeof (value as { t?: unknown }).t === "string" &&
(value as { t: string }).t.length > 0;
} Try / catch
try {
const msg = await decodeMessage(wasm, payload, key);
dispatch(msg);
} catch (error) {
if (error instanceof Error && error.message === "Peer message did not include a type") {
// Malformed peer message: log and drop it, keep the connection alive
console.warn("dropping untyped peer message");
return;
}
throw error;
} Prevention
- Always include the 't' type field when constructing peer messages in tests or custom senders.
- Keep both peers on compatible croc protocol versions before relaying messages.
- Log the decoded-but-untyped payload once to identify which peer emits schema-violating messages.
When it happens
Trigger: Calling decodeMessage(wasm, payload, key) where payload decrypts/decompresses to valid JSON without a 't' property (e.g. {"v":1} or an unrelated JSON object). Happens when a peer sends an untyped message, a sender/receiver version mismatch changes the wire schema, or a test feeds hand-crafted JSON through the codec.
Common situations: Interop testing between the browser client and a non-standard/modified croc peer; protocol version drift after upgrading one side; unit tests that build fake peer messages and forget the 't' field; replaying captured frames with a wrong key that happens to yield valid JSON.
Related errors
- Peer sent an unexpected control handshake
- Relay returned an invalid port list: ${banner}
- Recipient did not start a croc PAKE handshake
- Recipient did not secure the channel
- Unexpected peer message: ${message.t}
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/f1d1d69f8ff7c884.
Report an issue: GitHub.