microsoft/semantic-kernel · error · RuntimeError

The task ledger is not initialized. Planning needs to happen

Error message

The task ledger is not initialized. Planning needs to happen first.

What it means

replan() reads self.task_ledger to update facts and the plan. That ledger is only created inside plan(), so calling replan on a manager that has never planned leaves task_ledger as None and the method cannot proceed. The manager enforces the plan-then-replan lifecycle.

Source

Thrown at python/semantic_kernel/agents/orchestration/magentic.py:332

            self.prompt_execution_settings,
        )
        assert plan is not None  # nosec B101

        self.task_ledger = _TaskLedger(facts=facts, plan=plan)
        return await self._render_task_ledger(magentic_context)

    @override
    async def replan(self, magentic_context: MagenticContext) -> ChatMessageContent:
        """Replan the task.

        Args:
            magentic_context (MagenticContext): The context for the Magentic manager.

        Returns:
            ChatMessageContent: The updated task ledger.
        """
        if self.task_ledger is None:
            raise RuntimeError("The task ledger is not initialized. Planning needs to happen first.")

        # 1. Update the facts
        prompt_template = KernelPromptTemplate(
            prompt_template_config=PromptTemplateConfig(template=self.task_ledger_facts_update_prompt)
        )
        magentic_context.chat_history.add_message(
            ChatMessageContent(
                role=AuthorRole.USER,
                content=await prompt_template.render(
                    Kernel(),
                    KernelArguments(task=magentic_context.task.content, old_facts=self.task_ledger.facts.content),
                ),
            )
        )
        facts = await self.chat_completion_service.get_chat_message_content(
            magentic_context.chat_history,
            self.prompt_execution_settings,
        )

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Call `await manager.plan(context)` first to initialize the task ledger before any replan.
  2. Drive the manager through MagenticOrchestration.invoke(), which calls plan/replan in the correct order automatically.
  3. If reusing the instance for a new task, reset by constructing a fresh StandardMagenticManager or re-running plan().

Example fix

// before
manager = StandardMagenticManager(service)
await manager.replan(context)  # raises: ledger is None

// after
manager = StandardMagenticManager(service)
await manager.plan(context)      # initializes task ledger
await manager.replan(context)    # ok
Defensive patterns

Strategy: validation

Validate before calling

# Ensure plan ran before replan
if getattr(manager, "task_ledger", None) is None:
    await manager.plan(context)  # initialize ledger
await manager.replan(context)

Type guard

def manager_has_plan(mgr) -> bool:
    return getattr(mgr, "task_ledger", None) is not None

Prevention

When it happens

Trigger: Calling `await manager.replan(context)` on a StandardMagenticManager instance whose `plan()` was never invoked (task_ledger is still its default None). Common when driving the manager manually instead of through MagenticOrchestration.

Common situations: Subclassing or scripting the manager directly and skipping the initial planning step. Reusing a manager instance for a new task without re-planning. Test code that exercises replan in isolation.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/214ec7552c25a6e0. Report an issue: GitHub.