tinyhumansai/openhuman · error
Channel connect response missing status
Error message
Channel connect response missing status
What it means
Thrown by normalizeConnectResult() when the 'openhuman.channels_connect' response object has no string 'status' field (status is read, coerced to '' when not a string, and the empty value throws). Connect results may carry optional restart_required/auth_action/message, but status is the one mandatory field the connect UI branches on.
Source
Thrown at app/src/services/api/channelConnectionsApi.ts:103
}
function expectDiscordLinkComplete(payload: unknown): DiscordLinkCheckResult {
const record = expectObject<Record<string, unknown>>(payload, 'Discord link complete');
if (typeof record.linked !== 'boolean') {
throw new Error('Discord link complete response missing required boolean field: linked');
}
const details =
record.details !== undefined && record.details !== null
? (record.details as Record<string, unknown>)
: null;
return { linked: record.linked, details };
}
function normalizeConnectResult(payload: unknown): ChannelConnectionResult {
const record = expectObject<Record<string, unknown>>(payload, 'Channel connect');
const status = typeof record.status === 'string' ? record.status : '';
if (!status) {
throw new Error('Channel connect response missing status');
}
return {
status,
restart_required: Boolean(record.restart_required),
auth_action: typeof record.auth_action === 'string' ? record.auth_action : undefined,
message: typeof record.message === 'string' ? record.message : undefined,
};
}
function normalizePermissionCheck(payload: unknown): BotPermissionCheck {
const record = expectObject<Record<string, unknown>>(payload, 'Discord permission check');
const missing = Array.isArray(record.missing_permissions)
? record.missing_permissions.filter((perm): perm is string => typeof perm === 'string')
: [];
return {
can_view_channel: Boolean(record.can_view_channel),
can_send_messages: Boolean(record.can_send_messages),
can_read_message_history: Boolean(record.can_read_message_history),View on GitHub (pinned to a221052e0d)
Solutions
- Restart the core / relaunch the app so both halves are the same build
- Reproduce with curl: openhuman.channels_connect with the same channel/authMode/credentials and inspect the result object
- Check the core logs for the specific channel's connect handler path — the shape is per-channel, so identify which channel produced it
- If developing the handler, map every exit path to a status string ('connected', 'failed', 'restart_required', ...)
Example fix
// before
{"success": false, "message": "bad token"}
// after
{"status": "failed", "message": "bad token", "restart_required": false} Defensive patterns
Strategy: type-guard
Type guard
function isConnectResult(v: unknown): v is { status: string; restart_required?: boolean; auth_action?: string; message?: string } {
const r = v as Record<string, unknown> | null | undefined;
const inner =
r && 'result' in r && 'logs' in r ? (r.result as Record<string, unknown>) : r;
return !!inner && typeof inner.status === 'string' && inner.status.length > 0;
} Try / catch
try {
const res = await channelConnectionsApi.connectChannel(channel, payload);
handleStatus(res.status);
} catch (e) {
if (e instanceof Error && e.message.includes('missing status')) {
showConnectError('Unexpected core response — update/restart the app and retry.');
} else throw e;
} Prevention
- Per-channel connect handlers diverge; contract-test the exact channel you touch
- Map every core-side exit path to a status string before shipping a handler change
- Resync app/core builds after partial updates before debugging deeper
When it happens
Trigger: connectChannel(channel, payload) resolves with a payload whose status is missing, null, or non-string — e.g. the core returned {success: false, message: '...'} instead of a status-bearing result, or a CLI envelope whose inner result lacks status.
Common situations: Core/frontend contract drift after updating one side only; a channel whose connect handler short-circuits with a differently-shaped object (per-channel handlers differ); channel compiled out by a feature gate returning a stub shape.
Related errors
- Discord link start response missing required string field: l
- Discord link start response missing required string field: i
- Discord link complete response missing required boolean fiel
- ${context} returned an invalid response shape
- provider_surfaces_list_queue: unexpected empty response
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/56344229f3a02618.
Report an issue: GitHub.