zylon-ai/private-gpt · error · Error
Empty response from generator.
Error message
Empty response from generator.
What it means
This RuntimeError is raised by the repo's spec-sync script scripts/update_claude_specs.py (update_openapi_spec_url, line 57). After reading tests/models/anthropic/test_openapi_schema.py it runs re.subn with the pattern ^(OPENAPI_SPEC_URL\s*=\s*")[^"]*(") (MULTILINE), and when the substitution count is 0 it aborts instead of writing anything. It means the module-level double-quoted OPENAPI_SPEC_URL constant the script is built to rewrite no longer exists in the expected textual shape.
Source
Thrown at ui/index.html:4799
' "customInstructions": "string",',
' "palette": { "accent": "#RRGGBB", "secondary": "#RRGGBB", "surface": "#RRGGBB", "background": "#RRGGBB" },',
' "features": { "databases": true, "web": true, "mcp": true, "skills": true, "customTools": true, "apiDebugger": true, "github": true, "productionNotice": true }',
"}",
"The brand name should be short.",
"The welcome title should be concise.",
"The welcome subtitle should be one sentence.",
"The custom instructions should guide the assistant to fit the described workspace.",
"Choose dark or light mode intentionally based on the brief and the palette.",
"The github field must always stay true.",
"Disable features only when the brief clearly implies a simpler surface.",
"",
`User brief: ${brief}`
].join("\n");
}
function extractJsonObject(text) {
const trimmed = String(text || "").trim();
if (!trimmed) throw new Error("Empty response from generator.");
try {
return JSON.parse(trimmed);
} catch {}
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i);
if (fenced) {
try { return JSON.parse(fenced[1].trim()); } catch {}
}
const start = trimmed.indexOf("{");
const end = trimmed.lastIndexOf("}");
if (start >= 0 && end > start) {
return JSON.parse(trimmed.slice(start, end + 1));
}
throw new Error("Generator did not return valid JSON.");
}
function normalizeAppearanceSuggestion(candidate, fallbackBrief = "") {
const appearance = {
...DEFAULT_APPEARANCE,View on GitHub (pinned to 4a030776a3)
Solutions
- Inspect tests/models/anthropic/test_openapi_schema.py and restore a top-level, column-0, double-quoted assignment: OPENAPI_SPEC_URL = "https://..." (currently at line 11).
- If the constant was intentionally renamed or moved, update OPENAPI_TEST_FILE and the regex in scripts/update_claude_specs.py (lines 16, 37, 51) to match the new location/shape — keep fetch (current_openapi_spec_url) and update (update_openapi_spec_url) patterns in sync.
- If the assignment is merely indented or re-quoted, either revert the formatting change or loosen the pattern (e.g. drop the ^ anchor or allow single quotes) so both the reader at line 37 and the writer at line 51 still agree.
- Re-run python scripts/update_claude_specs.py and confirm it prints the '... -> ...' URL update without raising.
Example fix
# tests/models/anthropic/test_openapi_schema.py — before (indented / single-quoted, count == 0)
class TestOpenAPI:
OPENAPI_SPEC_URL = 'https://storage.googleapis.com/...'
# after (top-level, double-quoted — matches ^(OPENAPI_SPEC_URL\s*=\s*")[^"]*("))
OPENAPI_SPEC_URL = "https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic/anthropic-506a5ad71d522b4ae56ac3429380486647af1f92eddde80603480fb592d62b54.yml" Defensive patterns
Strategy: validation
Validate before calling
# Pre-flight check mirroring both the reader (line 37) and writer (line 51) regexes
import re
from pathlib import Path
OPENAPI_TEST_FILE = Path("tests/models/anthropic/test_openapi_schema.py")
READ_RE = re.compile(r'^OPENAPI_SPEC_URL\s*=\s*"([^"]*)"', re.MULTILINE)
WRITE_RE = re.compile(r'^(OPENAPI_SPEC_URL\s*=\s*")[^"]*(")', re.MULTILINE)
def openapi_pin_is_rewriteable() -> bool:
source = OPENAPI_TEST_FILE.read_text(encoding="utf-8")
return bool(READ_RE.search(source)) and len(WRITE_RE.findall(source)) == 1
# call before running scripts/update_claude_specs.py
if not openapi_pin_is_rewriteable():
raise SystemExit("test_openapi_schema.py: OPENAPI_SPEC_URL pin missing or not rewriteable — fix before sync") Try / catch
import subprocess, sys
try:
subprocess.run([sys.executable, "scripts/update_claude_specs.py"], check=True)
except subprocess.CalledProcessError:
# Abort the CI job; the error message names the file and the missing constant.
# Fix the source file, do not retry — the failure is deterministic, not transient.
sys.exit("update_claude_specs failed: check OPENAPI_SPEC_URL in tests/models/anthropic/test_openapi_schema.py") Prevention
- Keep OPENAPI_SPEC_URL as a column-0, double-quoted module-level constant in tests/models/anthropic/test_openapi_schema.py; document this contract next to the constant.
- Exclude tests/models/anthropic/test_openapi_schema.py's constant line from formatters (or configure them to preserve top-level constants and quote style), since indentation or single quotes silently breaks the ^-anchored regex.
- When refactoring the conformance test, grep scripts/update_claude_specs.py for OPENAPI_SPEC_URL and update the reader/writer regex pair together — they must match the identical shape.
- Add a cheap CI or pre-commit assertion that re.search(r'^OPENAPI_SPEC_URL\s*=\s*"', source, re.M) still matches, so drift is caught at PR time instead of when upstream publishes a new spec URL.
When it happens
Trigger: Concrete shapes of tests/models/anthropic/test_openapi_schema.py that yield count == 0: (1) the constant was renamed or deleted (e.g. refactored to SPEC_URL); (2) the assignment is indented or nested (the ^ anchor with re.MULTILINE only matches at column 0, so ' OPENAPI_SPEC_URL = ...' never matches); (3) the value uses single quotes, an f-string, or is split across lines; (4) the URL pin was moved to a different file while OPENAPI_TEST_FILE at scripts/update_claude_specs.py:16 still points here. It is raised only when the fetched .stats.yml URL differs from the pinned one, i.e. inside update_openapi_spec_url called from main() at line 95.
Common situations: Typically hit in CI (.github/workflows/update-claude-specs.yml) after someone refactors the OpenAPI conformance test — reformatting with a formatter that indents the constant, switching quote style, or extracting the URL into a fixture/config. Also occurs when a new spec URL is published upstream, because the error path only executes when pinned != latest; an up-to-date pin silently passes even if the constant is malformed.
Related errors
- Generator did not return valid JSON.
- Invalid CALL statement format
- openapi_spec_url not found in {ANTHROPIC_STATS_URL}
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/a4e5a302d1172a43.
Report an issue: GitHub.