nanocoai/nanoclaw · error · Error
bad request shape
Error message
bad request shape
What it means
The ncl Unix-socket server parses each newline-delimited frame as JSON and requires it to match the RequestFrame shape; malformed JSON or a wrong shape yields this error reply (wrapped from JSON.parse or the isRequestFrame guard).
Source
Thrown at src/cli/socket-server.ts:76
buffer += chunk.toString('utf8');
let idx: number;
while ((idx = buffer.indexOf('\n')) >= 0) {
const line = buffer.slice(0, idx).trim();
buffer = buffer.slice(idx + 1);
if (!line) continue;
void handleFrame(conn, line);
}
});
conn.on('error', (err) => {
log.warn('ncl CLI server connection error', { err });
});
}
async function handleFrame(conn: net.Socket, line: string): Promise<void> {
let req: RequestFrame;
try {
const parsed: unknown = JSON.parse(line);
if (!isRequestFrame(parsed)) throw new Error('bad request shape');
req = parsed;
} catch (e) {
write(conn, {
id: 'unknown',
ok: false,
error: {
code: 'transport-error',
message: `bad frame: ${e instanceof Error ? e.message : String(e)}`,
},
});
return;
}
// Host caller — connecting to data/ncl.sock requires file-system access
// to a 0600 socket owned by the host user, so we treat the socket path
// itself as the auth boundary.
const ctx: CallerContext = { caller: 'host' };
const res = await dispatch(req, ctx);View on GitHub (pinned to 294ef2aee8)
Solutions
- Send valid JSON matching the RequestFrame shape the server expects
- Use the provided ncl client / socket transport instead of hand-rolled frames
- If a version mismatch, restart the socket server and use the matching ncl build
Example fix
# before
echo 'wirings list' | nc -U /path/to/socket
# after (one JSON request frame per line)
echo '{"id":"1","command":"wirings","verb":"list","args":{}}' | nc -U /path/to/socket Defensive patterns
Strategy: type-guard
Validate before calling
const line = JSON.stringify({ id: '1', command: 'groups', verb: 'list', args: {} }); Type guard
function isRequestFrame(x: unknown): x is RequestFrame {
return typeof x === 'object' && x !== null && 'id' in x && 'command' in x;
} Try / catch
try { await handleFrame(conn, line); } catch { write(conn, { id: 'unknown', ok: false, error: { message: 'bad request shape' } }); } Prevention
- Always use the shipped ncl client over the raw socket
- One JSON frame per line; validate before sending
When it happens
Trigger: Sending a non-JSON line, or a JSON value missing required RequestFrame fields (id, command structure), to the ncl socket.
Common situations: Custom scripts speaking the socket protocol by hand, version skew between client and server frame format, or debugging with netcat and forgetting quotes.
Related errors
- ${flag} must be valid JSON
- ${settingsFile} hooks must be a JSON object
- session_mode 'per-thread' requires honored thread ids, but t
- --${column.name.replace(/_/g, '-')} must be true or false
- ${def.name} id is required
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/6550d68fd092546e.
Report an issue: GitHub.