jackwener/OpenCLI · error · CommandExecutionError

semanticscholar search returned an unexpected payload shape

Error message

semanticscholar search returned an unexpected payload shape

What it means

The Semantic Scholar /paper/search endpoint is expected to return an object with a `data` array of paper results. This library throws a CommandExecutionError when the response JSON either is not an object or lacks an array-shaped `data` field, i.e. the payload does not match the documented Graph API search schema. It guards callers from dereferencing `body.data` on a malformed or schema-changed response.

Source

Thrown at clis/semanticscholar/search.js:40

    access: 'read',
    description: 'Search Semantic Scholar papers by free text',
    domain: 'api.semanticscholar.org',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'query', positional: true, required: true, help: 'Search text (e.g. "attention is all you need", "diffusion model")' },
        { name: 'limit', type: 'int', default: 20, help: 'Max papers (1-100, single Semantic Scholar page)' },
    ],
    columns: ['rank', 'paperId', 'doi', 'title', 'year', 'firstAuthor', 'citationCount', 'url'],
    func: async (args) => {
        const query = requireString(args.query, 'query');
        const limit = requireBoundedInt(args.limit, 20, 100);
        const url = `${S2_GRAPH_BASE}/paper/search?query=${encodeURIComponent(query)}&limit=${limit}&fields=${FIELDS}`;
        const body = await s2Fetch(url, 'semanticscholar search');

        const data = Array.isArray(body?.data) ? body.data : null;
        if (data === null) {
            throw new CommandExecutionError('semanticscholar search returned an unexpected payload shape');
        }
        if (!data.length) {
            throw new EmptyResultError('semanticscholar search', `No Semantic Scholar papers matched "${query}".`);
        }

        return data.slice(0, limit).map((p, i) => normalizePaperRow(p, 'search', { rank: i + 1 }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the raw response body (e.g. curl the same URL with your SEMANTIC_SCHOLAR_API_KEY) and inspect the actual JSON shape to see what deviated.
  2. Check status.semanticscholar.org / the Graph API changelog for a schema change to /paper/search and update the adapter or library.
  3. Retry after a short wait if a transient gateway was substituting error bodies; verify network path to api.semanticscholar.org.
  4. If a proxy is rewriting responses, bypass it or add it to NO_PROXY so the client talks to the API directly.

Example fix

// before
const data = Array.isArray(body?.data) ? body.data : null;
if (data === null) {
    throw new CommandExecutionError('semanticscholar search returned an unexpected payload shape');
}
// after (log the offending payload to debug)
const data = Array.isArray(body?.data) ? body.data : null;
if (data === null) {
    throw new CommandExecutionError(
        `semanticscholar search returned an unexpected payload shape: ${JSON.stringify(body).slice(0, 300)}`,
    );
}
Defensive patterns

Strategy: type-guard

Type guard

function isSearchPayload(body) {
    return body != null && typeof body === 'object' && Array.isArray(body.data);
}
// usage: if (!isSearchPayload(body)) throw new CommandExecutionError('unexpected payload shape');

Try / catch

try {
    const rows = await searchPapers(query);
} catch (err) {
    if (err instanceof CommandExecutionError && /unexpected payload shape/.test(err.message)) {
        logger.error('S2 search schema drift', err.message);
    } else throw err;
}

Prevention

When it happens

Trigger: Calling `opencli semanticscholar search <query>` when the API responds 200 with JSON whose `data` property is missing, null, or not an array (e.g. an error envelope like `{message, error}` slipped past body.error checks, a proxy returned a different JSON shape, or Semantic Scholar changed the search response schema).

Common situations: Corporate proxies or captive portals injecting JSON error bodies; Semantic Scholar returning an API-level error object with a 200 status; API version drift (Graph v1 schema change); hitting a mirror/gateway that does not proxy the Graph API faithfully.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/47c2013bf75e8dc2. Report an issue: GitHub.