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

  1. 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).
  2. 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.
  3. 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.
  4. 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

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


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/a4e5a302d1172a43. Report an issue: GitHub.