jackwener/OpenCLI · error · CommandExecutionError
expected array of rows from server, got ${typeof rows} (cont
Error message
expected array of rows from server, got ${typeof rows} (contract drift?) What it means
message-search.js expects the normalized evaluate result to be an array of message rows which it then maps to output columns. If dispatchEvaluateResult returns a non-array it throws this CommandExecutionError, signaling the server response no longer matches the CLI's expected contract (the snippet itself already coerces bare arrays or objects with results/messages/data).
Source
Thrown at clis/slock/message-search.js:62
const arr = await cres.json();
const hit = (Array.isArray(arr)?arr:(arr.channels||arr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${target});
if (!hit) return { kind: 'unresolvable', detail: 'no channel matches ' + ${JSON.stringify(channel)} };
channelId = hit.id;
}
}
const searchUrl = '${SLOCK_API_BASE}/messages/search?q=' + encodeURIComponent(${JSON.stringify(q)}) + (channelId ? '&channelId=' + encodeURIComponent(channelId) : '') + '&limit=' + encodeURIComponent(${JSON.stringify(limit)});
const res = await fetch(searchUrl, { credentials:'include', headers });
if (!res.ok) return { kind: res.status===401?'auth':'http', status: res.status, where:'/messages/search' };
const data = await res.json();
// F2-b — qatester live dump: shape is { results: [...], hasMore }.
// Unwrap .results first; fall back to legacy .messages / .data /
// bare array for forward-compat.
return { kind: 'ok', rows: Array.isArray(data) ? data : (data.results || data.messages || data.data || []) };
`;
const result = await page.evaluate(`(async () => { ${snippet} })()`);
const rows = dispatchEvaluateResult(result);
if (!Array.isArray(rows)) {
throw new CommandExecutionError(`expected array of rows from server, got ${typeof rows} (contract drift?)`);
}
return rows.map((m) => ({
id: m.id ?? m.messageId ?? '',
channelId: m.channelId ?? '',
createdAt: m.createdAt ?? m.created_at ?? '',
senderName: m.sender?.name ?? m.user?.name ?? '',
content: m.content ?? '',
}));
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Extend the fallback chain in the snippet's return line to include the new field name (e.g. data.hits || data.matches).
- Log `result`/`rows` before the throw to see the actual envelope.
- Verify auth and active server so the search endpoint returns real rows.
- Update the CLI to match the current server search contract.
Example fix
// before
return { kind: 'ok', rows: Array.isArray(data) ? data : (data.results || data.messages || data.data || []) };
// after
return { kind: 'ok', rows: Array.isArray(data) ? data : (data.results || data.messages || data.data || data.hits || []) }; Defensive patterns
Strategy: type-guard
Validate before calling
const rows = dispatchEvaluateResult(result);
if (!Array.isArray(rows)) throw new Error(`unexpected search payload: ${JSON.stringify(rows).slice(0,200)}`); Type guard
function isSearchRows(v) { return Array.isArray(v); } Try / catch
try { const rows = await searchMessages(page, kwargs); } catch (e) { if (String(e.message).includes('expected array of rows from server')) { console.error('Search response contract drift — check envelope field names'); } else throw e; } Prevention
- Extend the snippet's envelope fallback chain when the server adds new field names
- Log raw results on first integration with a new server
- Convert API error objects into thrown errors inside dispatchEvaluateResult
When it happens
Trigger: The endpoint returns an envelope field the snippet doesn't know (e.g. `hits`, `matches`); an auth/error object passes through dispatchEvaluateResult as a non-array; the snippet returns {kind:'error'} shape unexpectedly.
Common situations: Server API upgrade renaming the results field; proxy injecting error bodies; degraded mode returning metadata instead of rows.
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
- expected files array, got ${typeof files} (contract drift?)
- expected array of rows from server, got ${typeof rows} (cont
- expected inbox items array, got ${typeof items} (contract dr
- expected array of rows from server, got ${typeof list} (cont
- workspace/create returned no workspace_id: ${JSON.stringify(
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9efc39b7ec755c9d.
Report an issue: GitHub.