tinyhumansai/openhuman · warning
Please paste a meeting link.
Error message
Please paste a meeting link.
What it means
Client-side validation in `joinMeetViaBackendBot`: `input.meetUrl.trim()` is empty. Thrown before any RPC, so the core/backend never saw the request. It guards the subsequent `openhuman.agent_meetings_join` call, which requires a join URL for the Recall.ai bot. Note the sibling `joinMeetingViaMascotBot` throws a plain object for the same condition — a caller catching Errors only would miss that one, but this function throws a real `Error`.
Source
Thrown at app/src/services/meetCallService.ts:228
listenOnly?: boolean;
};
type CoreBackendMeetJoinResponse = { ok: boolean; meet_url: string; platform: string };
/**
* Join a meeting via the backend's Recall.ai bot. Supports Google Meet,
* Zoom, Microsoft Teams, and Webex.
*
* Calls the core RPC `openhuman.agent_meetings_join`, which emits `bot:join`
* over the core's persistent Socket.IO connection to the backend. The backend
* streams events back (`bot:reply`, `bot:harness`, `bot:transcript`, `bot:left`)
* which the core bridges to the frontend as `agent_meetings:*` socket events.
*/
export async function joinMeetViaBackendBot(
input: BackendMeetJoinInput
): Promise<{ meetUrl: string; platform: string }> {
const meetUrl = input.meetUrl.trim();
if (!meetUrl) throw new Error('Please paste a meeting link.');
// Dual-mascot slots (issue #4277), mapped to the backend's snake_case wire
// shape. Absent → backend falls back to `mascot_id`.
const slots = input.mascots?.filter(m => m.mascotId?.trim());
const mascots =
slots && slots.length > 0
? slots.map(m => ({
mascot_id: m.mascotId.trim(),
name: m.name?.trim() || undefined,
voice_id: m.voiceId?.trim() || undefined,
rive_colors: mapRiveColors(m.riveColors),
}))
: undefined;
// Flow/state metadata only — no participant names, voices, or the meet URL.
log(
'backend bot join corr=%s dual=%s slots=%d singleMascot=%s riveColors=%s',
input.correlationId?.trim() || '-',View on GitHub (pinned to a221052e0d)
Solutions
- Disable the Join button until `meetUrl.trim()` is non-empty
- Validate supported URL shape earlier (meet.google.com / zoom.us / teams.microsoft.com / webex) for a better message
- In catch handlers, show this message as a form-field hint, not a crash banner
Example fix
// before
<button onClick={() => joinMeetViaBackendBot({ meetUrl, ... })}>Join</button>
// after
<button disabled={!meetUrl.trim()}
onClick={() => joinMeetViaBackendBot({ meetUrl, ... })}>Join</button> Defensive patterns
Strategy: validation
Validate before calling
const url = meetUrl.trim();
if (!url) {
setFieldError('Please paste a meeting link.');
return;
}
await joinMeetViaBackendBot({ ...input, meetUrl: url }); Prevention
- Disable submit until the URL field has non-whitespace content
- Prefer validating at the form layer with a specific field message over relying on the thrown error
- Remember the mascot-bot sibling throws a plain object for the same condition — guard input before either call
When it happens
Trigger: Join form submitted with an empty or whitespace-only URL field; UI wiring passes an uncontrolled input's initial value; a deep link / automation invokes the join flow without a URL parameter.
Common situations: Form submit handler not disabling the button until the field is non-empty; e2e tests driving the form with blank input; programmatic callers (flows) omitting meetUrl.
Related errors
- Core rejected the agent_meetings_join request.
- Core rejected the meet_list_upcoming request.
- Finish choosing how OpenHuman runs (tap Continue on the setu
- OpenHuman could not reach its remote (cloud) runtime. Check
- agentTeamApi: ${label} must be a positive integer
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/f3e5508d86649a72.
Report an issue: GitHub.