Skip to content

[Bug]: Docker playground — custom Advanced Config always 400s (/config/dump call omits required type field) #2059

Description

@rwb-truelime

crawl4ai version

0.9.0 (Docker server). Also present on develop — see below.

Summary

In the Docker playground (/playground), entering any Advanced Config (CrawlerRunConfig or BrowserConfig) and clicking Run immediately fails with:

{ "error": "{\"detail\":\"type must be 'CrawlerRunConfig' or 'BrowserConfig'\"}" }

The playground's client JS calls POST /config/dump with only { code }, but the 0.9.0 endpoint requires a type field, so every custom config is rejected with HTTP 400. There is no way to use a custom CrawlerRunConfig/BrowserConfig from the playground.

Steps to reproduce

  1. Run the 0.9.0 Docker server with a token set (so the UI is reachable).
  2. Open /playground and expand ▶ Advanced Config — it defaults to CrawlerRunConfig(stream=True, cache_mode=CacheMode.BYPASS).
  3. Click Run.

Result: the Response panel shows type must be 'CrawlerRunConfig' or 'BrowserConfig'. Reproduces for stream=True and stream=False, and for the BrowserConfig template.

Root cause

Client omits typedeploy/docker/static/playground/index.html, pyConfigToJson():

const res = await fetch('/config/dump', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ code }),   // <-- no `type`
});

Server requires typedeploy/docker/server.py, _config_from_json() (called by POST /config/dump):

config_type = data.get("type")
if config_type == "CrawlerRunConfig":
    ...
elif config_type == "BrowserConfig":
    ...
else:
    raise ValueError("type must be 'CrawlerRunConfig' or 'BrowserConfig'")

The UI already knows the type — it is selected in the #cfg-type <select> (CrawlerRunConfig / BrowserConfig) that drives the config templates — it simply isn't sent in the request body.

Evidence

# omitting type -> HTTP 400
$ curl -sX POST .../config/dump -H 'Content-Type: application/json' \
    -d '{"code":"CrawlerRunConfig(stream=False, cache_mode=CacheMode.BYPASS)"}'
{"detail":"type must be 'CrawlerRunConfig' or 'BrowserConfig'"}

# including type -> HTTP 200
$ curl -sX POST .../config/dump -H 'Content-Type: application/json' \
    -d '{"type":"CrawlerRunConfig","code":"CrawlerRunConfig(stream=False, cache_mode=CacheMode.BYPASS)"}'
{"type":"CrawlerRunConfig","params":{ ... }}

Fix (one line)

Send the selected type from #cfg-type in pyConfigToJson():

             const res = await fetch('/config/dump', {
                 method: 'POST',
                 headers: { 'Content-Type': 'application/json' },
-                body: JSON.stringify({ code }),
+                body: JSON.stringify({ type: document.getElementById('cfg-type').value, code }),
             });

Verified: with this change /config/dump returns 200, and the subsequent POST /crawl with the resulting crawler_config returns a normal batch result ("success": true).

Still present on develop

The develop branch (which has the merged auth-gate fix #2039) still omits type in the same call — it uses authFetch('/config/dump', { ... body: JSON.stringify({ code }) }) (~line 569) — so this bug is not fixed there.

Secondary symptom (same broken path, FYI)

Because the 400 is caught and the fallback sets advConfig = { crawler_config: { stream: true } }, while shouldUseStream() checks crawler_config.params.stream (different nesting), the default stream=True template makes the client send a streaming request but parse it as batch. The server then returns NDJSON ({…result…}\n{"status":"completed"}) and response.json() throws SyntaxError: Unexpected non-whitespace character after JSON … (line 2 column 1). Fixing the type omission above resolves the custom-config 400; the shouldUseStream nesting mismatch looks like a related follow-up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐞 BugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions