tinyhumansai/openhuman · error

provider_surfaces_list_queue: unexpected empty response

Error message

provider_surfaces_list_queue: unexpected empty response

What it means

Thrown by parseQueueEnvelope() in providerSurfacesApi when the raw value returned by 'openhuman.provider_surfaces_list_queue' is falsy or not an object (undefined, null, string, number). Note the asymmetry: an object with a malformed/missing items payload is tolerated and returned as EMPTY_QUEUE — this error fires only when there is no object at all to parse.

Source

Thrown at app/src/services/api/providerSurfacesApi.ts:13

import type { RespondQueueList } from '../../types/providerSurfaces';
import { callCoreRpc } from '../coreRpcClient';

interface ProviderSurfacesQueueEnvelope {
  data?: RespondQueueList;
  result?: { data?: RespondQueueList };
}

const EMPTY_QUEUE: RespondQueueList = { items: [], count: 0 };

function parseQueueEnvelope(raw: unknown): RespondQueueList {
  if (!raw || typeof raw !== 'object') {
    throw new Error('provider_surfaces_list_queue: unexpected empty response');
  }

  const envelope = raw as ProviderSurfacesQueueEnvelope & { error?: { message?: string } };
  if (envelope.error) {
    throw new Error(envelope.error.message ?? 'Core RPC returned an error');
  }
  const candidate = envelope.result?.data ?? envelope.data;
  if (!candidate || !Array.isArray(candidate.items) || typeof candidate.count !== 'number') {
    return EMPTY_QUEUE;
  }
  return candidate;
}

export const providerSurfacesApi = {
  async listQueue(): Promise<RespondQueueList> {
    const raw = await callCoreRpc<unknown>({ method: 'openhuman.provider_surfaces_list_queue' });
    return parseQueueEnvelope(raw);
  },

View on GitHub (pinned to a221052e0d)

Solutions

  1. Confirm the core registers the method: GET /schema must list provider_surfaces_list_queue
  2. Update the desktop app and core together so the provider-surfaces surface exists on both sides
  3. If writing tests, make the callCoreRpc mock resolve {data: {items: [], count: 0}} or {result: {data: ...}} instead of undefined
  4. If developing the Rust controller, never return a bare null result — return {items: [], count: 0}

Example fix

// test/mock: before
vi.mocked(callCoreRpc).mockResolvedValue(undefined as any);

// after
vi.mocked(callCoreRpc).mockResolvedValue({ data: { items: [], count: 0 } });
Defensive patterns

Strategy: fallback

Validate before calling

// Probe with the raw RPC before relying on the helper:
const raw = await callCoreRpc<unknown>({ method: 'openhuman.provider_surfaces_list_queue' });
if (!raw || typeof raw !== 'object') {
  useEmptyQueue(); // core predates the surface — do not call providerSurfacesApi.listQueue
}

Type guard

function isQueuePayload(v: unknown): v is { items: unknown[]; count: number } {
  const r = v as Record<string, unknown> | null | undefined;
  const cand = (r?.result as Record<string, unknown> | undefined)?.data ?? r?.data;
  return !!cand && Array.isArray((cand as any).items) && typeof (cand as any).count === 'number';
}

Try / catch

try {
  const queue = await providerSurfacesApi.listQueue();
  renderQueue(queue);
} catch (e) {
  if (e instanceof Error && e.message.includes('unexpected empty response')) {
    renderQueue({ items: [], count: 0 }); // degrade gracefully — queue view is non-critical
  } else throw e;
}

Prevention

When it happens

Trigger: callCoreRpc resolves with undefined (a mocked client in tests returning nothing, or a wrapper that reads a missing key), or the JSON-RPC result is literally null (a core controller returning Option::None serialized as null).

Common situations: Core version predating the provider_surfaces controller while the frontend ships it; a Vitest mock of callCoreRpc that returns undefined instead of a payload; the method returning null before the respond-queue store initializes.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/585711770c291980. Report an issue: GitHub.