docling-project/docling · error · ValueError
submit_batch() received both 'target' and 'targets'; supply
Error message
submit_batch() received both 'target' and 'targets'; supply only one.
What it means
submit_batch() on the async service client accepts either 'target' (single target) or keyword-only 'targets' (list), never both. Supplying both is ambiguous — the API payload would need to choose one 'target'/'targets' field — so the client raises ValueError before building the BatchConvertSourcesRequest. This is a caller-side API misuse error, not a server error.
Source
Thrown at docling/service_client/_async_client.py:316
async def submit_batch(
self,
sources: Sequence[BatchSourceRequestInput],
target: BatchTargetRequestInput | None = None,
output_formats: list[OutputFormat] | None = None,
options: ConvertDocumentsRequestOptions | None = None,
headers: dict[str, str] | None = None,
*,
targets: list[BatchTargetRequestInput] | None = None,
) -> (
AsyncConversionJob[PresignedUrlConvertDocumentResponse]
| AsyncConversionJob[PresignedUrlConvertResponse]
):
assert self._async_client is not None, "client not open — use async with"
if target is None and targets is None:
raise ValueError("submit_batch() requires either 'target' or 'targets'.")
if target is not None and targets is not None:
raise ValueError(
"submit_batch() received both 'target' and 'targets'; supply only one."
)
payload: dict[str, Any] = {"sources": sources}
if targets is not None:
payload["targets"] = targets
else:
payload["target"] = target
request = BatchConvertSourcesRequest.model_validate(payload)
resolved = self._resolve_options(
options=options,
max_num_pages=None,
max_file_size=None,
page_range=None,
)
# Use the first effective target for output-format hint.
first_target = (request.targets or [request.target])[0]
submit_options = self._options_for_output_formats(
resolved.options,View on GitHub (pinned to 61d76f1ff3)
Solutions
- Keep exactly one of the two: drop target= when migrating to targets=[...], or vice versa.
- If wrapping submit_batch, decide which form your wrapper exposes and forward only that parameter.
- Add a unit assertion in wrappers that never both are set.
Example fix
# before job = await client.submit_batch(sources=s, target=t, targets=[t, t2]) # after job = await client.submit_batch(sources=s, targets=[t, t2])
Defensive patterns
Strategy: validation
Validate before calling
assert not (target is not None and targets is not None), 'pass only one of target/targets'
Prevention
- When migrating to targets=[...], delete the old target= argument.
- Avoid **kwargs forwarding around submit_batch; be explicit.
When it happens
Trigger: Calling submit_batch(sources=..., target=..., targets=[...]) with both populated; refactoring code from single-target to multi-target and leaving the old target= argument in place; framework code that forwards **kwargs containing target while also passing targets explicitly.
Common situations: Migrating an existing submit_batch call to the plural API without removing the old argument; generic wrapper functions that pass all options through; IDE autocompletion adding both parameters.
Related errors
- submit_batch() requires either 'target' or 'targets'.
- Response schema mismatch — client and server versions may di
- Unsupported URL scheme: '{scheme}'. Only http:// and https:/
- {name} must be between 1 and {MAX_CONCURRENCY_LIMIT}, got {v
- Cannot convert Box Note with hash {self.document_hash}: no '
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/ececc10acda3bd98.
Report an issue: GitHub.