langgenius/dify · warning · InvalidActionError
invalid_action
invalid_action
Error message
Document is being indexed, please try again later
What it means
Returned (HTTP 400, error_code `invalid_action`) by the segment enable/disable endpoint when a Redis flag `document_{document.id}_indexing` is still set. The flag is written while a document is being indexed/re-indexed and acts as a concurrency lock so segment status cannot be mutated mid-index. It is a transient, retryable rejection, not a data problem.
Source
Thrown at api/controllers/console/datasets/datasets_segments.py:395
model_manager = ModelManager.for_tenant(tenant_id=current_tenant_id)
model_manager.get_model_instance(
tenant_id=current_tenant_id,
provider=dataset.embedding_model_provider,
model_type=ModelType.TEXT_EMBEDDING,
model=dataset.embedding_model,
)
except LLMBadRequestError:
raise ProviderNotInitializeError(
"No Embedding Model available. Please configure a valid provider in the Settings -> Model Provider."
)
except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description)
segment_ids = request.args.getlist("segment_id")
document_indexing_cache_key = f"document_{document.id}_indexing"
cache_result = redis_client.get(document_indexing_cache_key)
if cache_result is not None:
raise InvalidActionError("Document is being indexed, please try again later")
try:
SegmentService.update_segments_status(segment_ids, action, dataset, document, session)
except Exception as e:
raise InvalidActionError(str(e))
return SimpleResultResponse(result="success").model_dump(mode="json"), 200
@console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segment")
class DatasetDocumentSegmentAddApi(Resource):
@console_ns.doc(params=SegmentDocParams.DATASET_DOCUMENT)
@setup_required
@login_required
@account_initialization_required
@cloud_edition_billing_resource_check("vector_space")
@cloud_edition_billing_knowledge_limit_check("add_segment")
@cloud_edition_billing_rate_limit_check("knowledge")
@console_ns.expect(console_ns.models[SegmentCreatePayload.__name__])
@console_ns.response(200, "Segment created successfully", console_ns.models[SegmentDetailResponse.__name__])View on GitHub (pinned to ef8544b173)
Solutions
- Wait for the document indexing job to finish, then retry the same enable/disable request.
- If indexing is genuinely done but the error persists, check whether a stale `document_{id}_indexing` key remains in Redis (e.g. `redis-cli GET document_<id>_indexing`) and delete it once you confirm no indexing task is running.
- Verify the Celery indexing worker is alive and the document's `indexing_status` is `completed` before retrying.
Example fix
// client: retry with backoff on invalid_action while document is indexing
async function toggleSegment(docId, segmentIds, action) {
for (let i = 0; i < 5; i++) {
const res = await fetch(`/console/api/datasets/${ds}/documents/${docId}/segments?action=${action}`,
{ method: 'PATCH', body: JSON.stringify({ segment_id: segmentIds }) });
if (res.status !== 400) return res;
const body = await res.json();
if (body.code !== 'invalid_action' || !/indexing/i.test(body.message)) throw body;
await new Promise(r => setTimeout(r, 1500 * (i + 1)));
}
throw new Error('Document still indexing after retries');
} Defensive patterns
Strategy: retry
Validate before calling
# Pre-flight: confirm the document is not actively indexing before toggling segments.
import requests
def safe_update_status(base, headers, dataset_id, document_id, segment_ids, action):
doc = requests.get(f"{base}/console/api/datasets/{dataset_id}/documents/{document_id}",
headers=headers).json()
status = doc.get("data", {}).get("indexing_status")
if status and status != "completed":
raise RuntimeError(f"document indexing_status={status}; wait and retry")
# optional: check the redis flag is unset via an admin endpoint if exposed
return requests.patch(
f"{base}/console/api/datasets/{dataset_id}/documents/{document_id}/segments",
headers=headers,
json={"segment_id": segment_ids, "action": action},
) Try / catch
# Treat invalid_action+indexing as transient and retry with backoff.
import time, requests
def update_status_with_retry(url, headers, payload, attempts=6, base_delay=1.5):
for i in range(attempts):
resp = requests.patch(url, headers=headers, json=payload)
if resp.status_code == 400:
body = resp.json()
if body.get("code") == "invalid_action" and "indexing" in (body.get("message") or "").lower():
time.sleep(base_delay * (i + 1))
continue
resp.raise_for_status()
return resp
raise RuntimeError("document still indexing after retries") Prevention
- Surface document indexing_status in the UI and disable the enable/disable toggle while it is not 'completed'.
- Ensure the indexing worker reliably clears the `document_{id}_indexing` Redis key on success AND failure.
- Add an orphaned-key cleanup that verifies no Celery indexing task is active before deleting stale locks.
When it happens
Trigger: Calling the segment status update endpoint (action=enable|disable) for a document whose indexing job has not finished clearing the `document_{id}_indexing` Redis key. Happens when a user toggles segment enable/disable immediately after uploading/re-indexing a document, or when a previous indexing run crashed and left the key orphaned.
Common situations: User re-indexes a document and clicks enable/disable on a segment before the indexing Celery task completes; a stalled/dead indexing worker leaves the Redis key behind so every subsequent toggle fails; Redis was flushed mid-index leaving inconsistent state.
Related errors
- completion_request_error
- document_indexing
- Recommended app not found
- App entity not found
- You can't install a non-public app
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/8e6a0638a3a7e436.
Report an issue: GitHub.