tinyhumansai/openhuman · error
Discord link complete response missing required boolean…
Error message
Discord link complete response missing required boolean field: linked
What it means
Thrown by expectDiscordLinkComplete() when the Discord link-status RPC response's `linked` field is not a boolean. The complete/poll call answers with linked: true/false (plus optional details) to say whether the user finished DMing the token to the bot; any other type (missing, string 'true', number, null) fails this strict check before the UI can branch on the pairing state.
Solutions
- Restart/update the core so link.complete returns {linked: boolean, details?}.
- Log the raw payload once at the failure point to see the actual type of `linked` and the record's keys.
- Fix test/mocks to return a real boolean for linked.
- If older cores legitimately send 'true'/'false' strings, coerce in the validator before the type check.
Example fix
// before
if (typeof record.linked !== 'boolean') {
throw new Error('Discord link complete response missing required boolean field: linked');
}
// after — coerce common encodings, still fail on genuinely missing data
const linked = typeof record.linked === 'boolean' ? record.linked
: record.linked === 'true' ? true
: record.linked === 'false' ? false
: null;
if (linked === null) {
throw new Error('Discord link complete response missing required boolean field: linked');
} Defensive patterns
Strategy: type-guard
Type guard
function isDiscordLinkCompletePayload(v: unknown): v is { linked: boolean; details?: Record<string, unknown> | null } {
return typeof (v as { linked?: unknown } | null)?.linked === 'boolean';
} Try / catch
try {
const { linked } = await checkDiscordLink();
} catch (e) {
if (e instanceof Error && e.message.includes('missing required boolean field: linked')) {
setStatus('unknown'); // stop polling, prompt user to relink
} else throw e;
} Prevention
- Polling loops should stop and surface 'relink' on schema failure instead of retrying forever.
- Return real booleans from mocks ({ linked: true }, not 'true').
- Version-lock core and UI before testing channel linking.
When it happens
Trigger: Core returned an error-shaped record without linked; a string/number boolean encoding from an older core or a hand-rolled test mock; unwrapCliEnvelope peeled the wrong envelope layer so the record is the envelope, not the payload; details present but linked dropped during JSON restructuring.
Common situations: Polling loop for Discord pairing runs against a stale core after a partial app update; test mocks that use {linked: 'true'}; core handler evolved to return {status: 'linked'} style payloads on some paths.
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
- Discord link start response missing required string field…
- Discord link start response missing required string field…
- Channel connect response missing status
- Core returned an empty backend URL
- Core RPC returned an error
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/2b56f280134fb96d.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/services/api/channelConnectionsApi.ts:90
}
return record as T;
}
function expectDiscordLinkStart(payload: unknown): DiscordLinkStartResult {
const record = expectObject<Record<string, unknown>>(payload, 'Discord link start');
if (typeof record.linkToken !== 'string' || !record.linkToken) {
throw new Error('Discord link start response missing required string field: linkToken');
}
if (typeof record.instructions !== 'string') {
throw new Error('Discord link start response missing required string field: instructions');
}
return { linkToken: record.linkToken, instructions: record.instructions };
}
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,View on GitHub (pinned to 7491200858)