BerriAI/litellm · error · NotImplementedError
Bedrock batch embedding currently supports only Amazon…
Error message
Bedrock batch embedding currently supports only Amazon Titan Text Embeddings V2 (model id contains 'titan-embed-text-v2'). Got model={model!r}. Track other embedding models in https://github.com/BerriAI/litellm/issues. What it means
LiteLLM's Bedrock batch path only implements the InvokeModel schema for Amazon Titan Text Embeddings V2. When the record's model (after litellm.model_alias_map resolution) does not contain 'titan-embed-text-v2', it refuses early instead of silently building a modelInput for the wrong provider, because each embedding model has a different InvokeModel body. The synchronous /v1/embeddings endpoint supports more models, but batch mappings for others are not yet written.
Solutions
- Switch the record's model to a Titan v2 id such as 'amazon.titan-embed-text-v2:0' (cross-region prefixes like 'us.amazon.titan-embed-text-v2:0' are detected via the substring fallback)
- If you must embed with Cohere/Titan G1/Nova, use the real-time /v1/embeddings path instead of batch
- Check litellm.model_alias_map for an override remapping your model to a non-Titan-v2 id
- File or upvote a GitHub issue (BerriAI/litellm) for the embedding model you need in batch
Example fix
// before (JSONL line)
{"custom_id": "req_1", "url": "/v1/embeddings", "body": {"model": "cohere.embed-english-v3:0", "input": "hello"}}
// after
{"custom_id": "req_1", "url": "/v1/embeddings", "body": {"model": "amazon.titan-embed-text-v2:0", "input": "hello"}} Defensive patterns
Strategy: fallback
Validate before calling
TITAN_V2 = "titan-embed-text-v2"
def batch_embedding_supported(model: str) -> bool:
return TITAN_V2 in model
assert all(batch_embedding_supported(r["body"]["model"]) for r in records if r.get("url") == "/v1/embeddings") Type guard
def is_titan_v2_embed_model(model: str) -> bool:
return "titan-embed-text-v2" in model Try / catch
try:
file = await client.files.create(file=batch_file, purpose="batch")
except NotImplementedError as e:
if "Titan Text Embeddings V2" in str(e):
# fall back to real-time embeddings for this workload
results = [await client.embeddings.create(model=m, input=x) for m, x in embedding_pairs] Prevention
- Standardize embedding batch jobs on amazon.titan-embed-text-v2:0 unless another model gets batch support
- Check litellm.model_alias_map so aliases don't resolve to unsupported embedding models
- Watch the LiteLLM changelog for new Bedrock batch embedding providers
When it happens
Trigger: A batch file containing an embedding record whose body.model is e.g. 'amazon.titan-embed-text-v1:0', 'cohere.embed-english-v3:0', or 'amazon.nova-embed-v1', or a model_alias_map entry that resolves to one of those. Also triggered when no model resolves and the target model string lacks the marker.
Common situations: Porting an existing OpenAI/Bedrock embedding batch job to LiteLLM files API; using a company alias that points at Cohere/Titan G1 embeddings; assuming batch parity with the sync /v1/embeddings model list.
Related errors
- Bedrock batch embedding `input` must be a string (or a…
- Embedding batch records do not have a chat-completion…
- Batch record for /v1/completions is missing required…
- Batch record for /v1/responses is missing required `input`…
- contents of file are None
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/72782dbca0307c72.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/bedrock/files/transformation.py:673
Currently routes Amazon Titan Text Embeddings V2 only; other
embedding providers (Titan G1, Titan Multimodal, Cohere Embed,
Nova Multimodal Embeddings) raise NotImplementedError until they
get a dedicated branch. Splitting them keeps PR scope tight and
lets each model's request schema be exercised by its own tests.
AWS docs (Titan v2 InvokeModel body):
https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-embed-text.html
"""
from litellm.llms.bedrock.embed.amazon_titan_v2_transformation import (
AmazonTitanV2Config,
)
if not self._is_titan_v2_embed_model(model):
# Refuse early instead of silently shaping the body for the wrong
# provider. The synchronous /v1/embeddings path supports more
# models, but each has a different InvokeModel schema; mapping
# them here without dedicated tests would risk corrupt batches.
raise NotImplementedError(
"Bedrock batch embedding currently supports only Amazon "
"Titan Text Embeddings V2 (model id contains "
f"'titan-embed-text-v2'). Got model={model!r}. Track other "
"embedding models in https://github.com/BerriAI/litellm/issues."
)
input_text: Final = self._coerce_embedding_input_to_string(openai_request_body.get("input"), model=model)
# Map OpenAI-style params (dimensions, encoding_format) onto the
# Titan v2 schema (dimensions, embeddingTypes) via the embed config
# so this stays in sync with the synchronous /v1/embeddings path.
non_default_params: Final = {k: v for k, v in openai_request_body.items() if k not in ("model", "input")}
titan_config: Final = AmazonTitanV2Config()
inference_params: Final = titan_config.map_openai_params(
non_default_params=non_default_params,
optional_params={},
)
return dict(titan_config._transform_request(input=input_text, inference_params=inference_params))View on GitHub (pinned to 77b7c6c40c)