Skip to content

Commit 34e4d8f

Browse files
ihor-sokoliukclaudecodex
committed
feat(search): make non-JSON search-response error actionable (FEAT-053)
When SearXNG returns a 200 with a non-JSON body and SEARXNG_HTML_FALLBACK is off, createJSONError now names both remediation fixes — enable `- json` under search.formats in settings.yml, or set SEARXNG_HTML_FALLBACK=true — while keeping the existing 100-char body preview. Closes the discoverability gap reported in #137. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-Authored-By: Codex <noreply@openai.com>
1 parent 5652ace commit 34e4d8f

3 files changed

Lines changed: 19 additions & 2 deletions

File tree

__tests__/unit/error-handler.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ async function runTests() {
9898
await testFunction('Specialized error creators', () => {
9999
const context = { searxngUrl: 'https://searx.example.com' };
100100

101-
assert.ok(createJSONError('invalid json') instanceof MCPSearXNGError);
101+
const jsonError = createJSONError('invalid json');
102+
assert.ok(jsonError instanceof MCPSearXNGError);
103+
assert.ok(jsonError.message.includes('invalid json'));
104+
assert.ok(jsonError.message.includes('- json'));
105+
assert.ok(jsonError.message.includes('search.formats'));
106+
assert.ok(jsonError.message.includes('SEARXNG_HTML_FALLBACK=true'));
102107
assert.ok(createDataError() instanceof MCPSearXNGError);
103108
assert.ok(createURLFormatError('invalid-url') instanceof MCPSearXNGError);
104109
assert.ok(createContentError('test error', 'https://example.com') instanceof MCPSearXNGError);

__tests__/unit/search.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,18 @@ async function runTests() {
276276
error.message.includes('Invalid JSON response'),
277277
`expected response preview in error message, got: ${error.message}`
278278
);
279+
assert.ok(
280+
error.message.includes('- json'),
281+
`expected SearXNG JSON format remediation in error message, got: ${error.message}`
282+
);
283+
assert.ok(
284+
error.message.includes('search.formats'),
285+
`expected SearXNG JSON format remediation in error message, got: ${error.message}`
286+
);
287+
assert.ok(
288+
error.message.includes('SEARXNG_HTML_FALLBACK=true'),
289+
`expected HTML fallback remediation in error message, got: ${error.message}`
290+
);
279291
}
280292

281293
fetchMocker.restore();

src/error-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export function createServerError(status: number, statusText: string, responseBo
113113

114114
export function createJSONError(responseText: string): MCPSearXNGError {
115115
const preview = responseText.substring(0, 100).replace(/\n/g, ' ');
116-
return new MCPSearXNGError(`🔍 SearXNG Response Error: Invalid JSON format. Response: "${preview}..."`);
116+
return new MCPSearXNGError(`🔍 SearXNG Response Error: Invalid JSON format. Response: "${preview}...". Enable - json under search.formats in your SearXNG settings.yml, or set SEARXNG_HTML_FALLBACK=true.`);
117117
}
118118

119119
export function createDataError(): MCPSearXNGError {

0 commit comments

Comments
 (0)