pydantic/monty · critical

current task is in unexpected Completed state after resolvin

Error message

current task is in unexpected Completed state after resolving futures: {:?}

What it means

After the host resolves pending futures, resume_with_resolved_futures re-examines the current task's state; a Completed state here means the task suspended even though it had already finished, which the scheduler never intends to do. It panics with the task's debug state. Internal scheduler invariant, not user-triggerable.

Source

Thrown at crates/monty/src/bytecode/vm/async_exec.rs:1022

            match task.state {
                TaskState::Failed(_) => {
                    // Current task failed - resume with exception so it can be caught by
                    // surrounding `try/except`.
                    let TaskState::Failed(err) = mem::replace(&mut task.state, TaskState::Ready) else {
                        unreachable!();
                    };
                    return self.resume_with_exception(err);
                }
                TaskState::Blocked(_) => {
                    // Current task is still blocked on unresolved futures.
                }
                TaskState::Ready => {
                    self.scheduler.remove_from_ready_queue(current_task_id);
                    return self.run_external();
                }
                TaskState::Completed(_) => {
                    // Should never have suspended if the task was completed
                    panic!(
                        "current task is in unexpected Completed state after resolving futures: {:?}",
                        task.state
                    );
                }
            }
        }

        // Current task was not able to resume, but there might be other ready tasks which can make
        // progress
        if let Some(next_task_id) = self.scheduler.next_ready_task() {
            self.save_current_context();
            self.scheduler.set_current_task(Some(next_task_id));
            self.load_or_init_task(next_task_id)?;
            return self.run_external();
        }

        let pending_call_ids = self.get_pending_call_ids();

View on GitHub (pinned to adc986b362)

Solutions

  1. Ensure every path that completes a task also removes it from pending resolution delivery
  2. Check handle_task_completion's waiter-handoff branch does not leave the completed task as current
  3. Assert the task is not Completed before registering it for future resolutions
  4. Report with a repro if triggered by plain asyncio-style code
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: The current task is marked Completed while parked awaiting external-future resolution — i.e. some path completed the task without removing it from the pending-await bookkeeping before resolutions were processed.

Common situations: Hit during development on task completion vs. suspension ordering in async_exec.rs.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/598c008ef7df75da. Report an issue: GitHub.