fix(search): don't fail the reindex when the embedding provider is unreachable - #31132
Conversation
…reachable #30364 un-gated the staged chunk recreate, so every job-driven full recreate now calls beginStagedChunkRecreate(), which opens with a pre-flight embed. The pre-flight rethrows, and that exception fails the whole SearchIndexApp run — so a reindex that needs no embeddings at all is now blocked by an optional AI provider being unreachable. That is not a narrow case. Collate ships semanticSearchEnabled=true by default while llmConfiguration.embeddings.provider defaults to bedrock, and BedrockEmbeddingClient's constructor never calls AWS — it validates the model id, dimension and region, then builds the SDK client. So on any deployment where a region resolves (anything on AWS) but bedrock:InvokeModel was never granted, the client constructs happily, initializeVectorSearchService reports success, and the first full reindex dies: User: arn:aws:sts::...:assumed-role/... is not authorized to perform: bedrock:InvokeModel on resource: .../amazon.titan-embed-text-v2:0 (Status Code: 403) surfacing as status='failed' within seconds with an empty failureContext. The misconfiguration is otherwise invisible: live indexing logs embedding errors and carries on, so the deployment looks healthy right up until someone reindexes. This is what has been failing the nightly Java IT suites on main and 2.0. Treat an unavailable provider as "do not stage" rather than "fail": return null, which the caller already handles as the partial-recreate outcome — existing chunks stay live and are swept by the next recreate that runs with a working provider. markEntityTypeReindexed already ignores marks from a run without staging, so this reuses a supported state rather than inventing one. Genuine staging failures — an indeterminate live-target probe, a failed index create — still throw, because those mean continuing could destroy live chunks.
Code Review ✅ ApprovedMakes embedding provider failures during search reindexing optional by returning null instead of throwing, allowing reindex jobs to complete when AI services are unreachable. No issues found. OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar | Powered by Gitar — free for open source |
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
Follows up #30364, which is on
mainand the2.0release branch.What happens today
#30364 un-gated the staged chunk recreate, so every job-driven full recreate now calls
beginStagedChunkRecreate(), which opens with a pre-flight embed. That pre-flight rethrows, and the exception fails the entireSearchIndexApprun — so a reindex that needs no embeddings at all is blocked by an optional AI provider being unreachable.Why this is not a narrow case
Collate ships
naturalLanguageSearch.semanticSearchEnabled=trueby default, whilellmConfiguration.embeddings.providerdefaults tobedrock. AndBedrockEmbeddingClient's constructor never calls AWS — it validates model id, dimension and region, then builds the SDK client.So on any deployment where a region resolves (anything running on AWS) but
bedrock:InvokeModelwas never granted:initializeVectorSearchServicereports success,surfacing as
status='failed'within seconds with an emptyfailureContext.The misconfiguration is otherwise invisible. Live indexing logs embedding errors and carries on, so the deployment looks healthy right up until someone reindexes. OSS is unaffected —
semanticSearchEnableddefaults tofalsethere, so the vector service never initialises and the gate returns early.This is what has been failing the nightly Java IT reindex suites on
mainand2.0since 2026-08-04.The change
Treat an unavailable provider as "do not stage" rather than "fail": return
null, which the caller already handles as the partial-recreate outcome — existing chunks stay live and get swept by the next recreate that runs with a working provider.markEntityTypeReindexedalready ignores marks from a run without staging (the "unbound chunk-type mark" branch), so this reuses a supported state rather than inventing one.The pre-flight's intent is preserved: it still refuses to stage a generation it could never finish. It just no longer takes the entity reindex down with it.
Genuine staging failures still throw — an indeterminate live-target probe, a failed index create — because those mean continuing could destroy live chunks. The existing
beginStagedChunkRecreate_abortsWhenTheLiveTargetProbeIsIndeterminatetest still passes unchanged.Test plan
OpenSearchVectorServiceChunkStagingTest— 8/8 pass, including a new case asserting an unavailable provider returnsnulland touches nothing in the cluster (verify(client, never()).indices()/.generic()).RecreateWithEmbeddingsTest— 7/7 pass.Unit tests were executed on
main; the2.0change is character-identical (verified by diffing the two patches) but its module could not be built locally offline.Related
🤖 Generated with Claude Code