OpenBMB/ChatDev · error · HTTPException

log_level must be one of DEBUG, INFO, WARNING, ERROR, CRITIC

Error message

log_level must be one of DEBUG, INFO, WARNING, ERROR, CRITICAL

What it means

run_workflow_sync converts request.log_level to the LogLevel enum; a ValueError yields HTTP 400 with the accepted list. Unlike the async/batch endpoints, this endpoint documents the full set DEBUG, INFO, WARNING, ERROR, CRITICAL.

Source

Thrown at server/routes/execute_sync.py:159

        "token_usage": token_usage,
        "output_dir": graph_context.directory,
    }
    return final_message, meta


def _sse_event(event_type: str, data: Any) -> str:
    payload = json.dumps(data, ensure_ascii=False, default=str)
    return f"event: {event_type}\ndata: {payload}\n\n"


@router.post("/api/workflow/run")
async def run_workflow_sync(request: WorkflowRunRequest, http_request: Request):
    try:
        resolved_log_level: Optional[LogLevel] = None
        if request.log_level:
            resolved_log_level = LogLevel(request.log_level)
    except ValueError:
        raise HTTPException(
            status_code=400,
            detail="log_level must be one of DEBUG, INFO, WARNING, ERROR, CRITICAL",
        )

    accepts_stream = _SSE_CONTENT_TYPE in (http_request.headers.get("accept") or "")
    if not accepts_stream:
        try:
            result = await run_in_threadpool(
                run_workflow,
                request.yaml_file,
                task_prompt=request.task_prompt,
                attachments=request.attachments,
                session_name=request.session_name,
                variables=request.variables,
                log_level=resolved_log_level,
            )
        except FileNotFoundError as exc:
            raise HTTPException(status_code=404, detail=str(exc))

View on GitHub (pinned to 4fb2db0ea9)

Solutions

  1. Use one of DEBUG, INFO, WARNING, ERROR, CRITICAL exactly as cased in the LogLevel enum
  2. Omit log_level to use the server default
  3. Normalize log level strings client-side against the accepted list before sending

Example fix

# before
"log_level": "trace"
# after
"log_level": "DEBUG"
Defensive patterns

Strategy: validation

Validate before calling

LEVELS = {'DEBUG','INFO','WARNING','ERROR','CRITICAL'}
if log_level is not None:
    assert log_level in LEVELS, f'log_level must be one of {LEVELS}'

Type guard

def is_valid_level(v: str | None) -> bool:
    return v is None or v in {'DEBUG','INFO','WARNING','ERROR','CRITICAL'}

Try / catch

except HTTPError as e:
    if e.response.status_code == 400 and 'log_level' in e.response.text:
        req['log_level'] = 'INFO'; client.run(req)

Prevention

When it happens

Trigger: POST to the sync workflow endpoint with log_level values like TRACE, FINE, lowercase variants not accepted by the enum, or arbitrary strings.

Common situations: Reusing log level strings from Python logging or log4j conventions that don't map to this enum; case sensitivity mismatches.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/1cdc66bb1f7faf9c. Report an issue: GitHub.