langgenius/dify · error · Error
streaming response body missing
Error message
streaming response body missing
What it means
Raised by DatasetsHitTestingBase._prepare_hit_testing_records when an individual element of the records list returned by HitTestingService.retrieve is not a dict. This is a defensive contract check that the retrieval service produced the expected record shape before response serialization. It is an internal/server-side failure, not caused by user input, and surfaces as a ValueError (HTTP 500 after the broad except in perform_hit_testing re-raises it).
Source
Thrown at cli/src/api/app-run.ts:62
// `http.stream` facade; stopTask / submitHumanInput are plain JSON and go through the
// generated oRPC contract. Both facades share this one transport.
this.orpc = createOpenApiClient(http)
}
async runStream(
appId: string,
body: Record<string, unknown>,
opts: StreamOptions = {},
): Promise<AsyncIterable<SseEvent>> {
const res = await this.http.stream(`apps/${encodeURIComponent(appId)}:run`, {
method: 'POST',
json: body,
headers: { Accept: 'text/event-stream' },
signal: opts.signal,
throwOnError: true,
retryOnRateLimit: opts.retryOnRateLimit,
})
if (res.body === null) throw new Error('streaming response body missing')
return normalizeDifyStream(parseSSE(res.body, opts.signal))
}
async stopTask(appId: string, taskId: string): Promise<void> {
await this.orpc.apps.byAppId.tasks.byTaskId.stop.post({
params: { app_id: appId, task_id: taskId },
})
}
async submitHumanInput(
appId: string,
formToken: string,
action: string,
inputs: Record<string, unknown>,
): Promise<void> {
await this.orpc.apps.byAppId.humanInputForms.byFormToken.submit.post({
params: { app_id: appId, form_token: formToken },
body: { action, inputs },View on GitHub (pinned to ef8544b173)
Solutions
- Inspect server logs for the full stack trace to identify which record and retrieval backend produced the non-dict value.
- Ensure any custom/external retrieval implementation returns records as plain dicts (call model_dump(mode='json') on ORM/pydantic objects before returning).
- Add a unit test against HitTestingService.retrieve output asserting every record is a dict with the expected keys.
Example fix
# before (retrieval service)
return {"query": q, "records": [some_segment_model, ...]}
# after
return {"query": q, "records": [s.model_dump(mode='json') if hasattr(s, 'model_dump') else s for s in segments]} Defensive patterns
Strategy: try-catch
Validate before calling
from typing import Any
def is_valid_records_payload(response: Any) -> bool:
return (
isinstance(response, dict)
and isinstance(response.get('records'), list)
and all(isinstance(r, dict) for r in response['records'])
)
# in retrieval service: assert is_valid_records_payload(result) before returning Type guard
from typing import Any
def is_hit_testing_record(value: Any) -> bool:
return isinstance(value, dict) Try / catch
try:
return DatasetsHitTestingBase._prepare_hit_testing_records(response.get('records', []))
except ValueError:
logger.exception('retrieve returned malformed records: %r', response.get('records'))
raise # surfaces as 500; this is a server-side contract bug, not retryable Prevention
- Maintain a contract test asserting HitTestingService.retrieve always returns list[dict] records.
- Call .model_dump(mode='json') on any pydantic/ORM segment before placing it in the records list.
- Log the raw response shape when this ValueError fires so regressions are diagnosable.
When it happens
Trigger: HitTestingService.retrieve returns a list whose element is None, a string, or a pydantic model that was not dumped to a dict. Typically the result of a custom retrieval backend, a malformed external knowledge adapter, or a regression in the retrieve service after a schema change.
Common situations: A plugin/external knowledge endpoint returns a non-object record; an in-development retrieval adapter forgets to call .model_dump() on segment objects; version skew between the retrieval service and the controller normalization layer.
Related errors
- usage_missing_arg
- export response missing data field
- reconnect stream body missing
- server_4xx_other
- usage_missing_arg
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/4c11db670a970ef0.
Report an issue: GitHub.