zylon-ai/private-gpt · error · RuntimeError

Unable to insert text

Error message

Unable to insert text

What it means

Raised by the text-editor insert tool when the underlying edit session reports a failed insert operation (session.insert returns success=False). The message is either the session's error detail or the generic 'Unable to insert text' fallback when the session gave no reason. It means the edit itself was rejected, not that the tool wiring failed.

Source

Thrown at private_gpt/components/tools/builders/text_editor_tool_builder.py:218

            ),
        )

    async def build_insert_tool(
        self,
        config: CodeExecutionSessionConfig,
        name: str = TEXT_EDITOR_INSERT_TOOL_NAME,
        type: str = TEXT_EDITOR_INSERT_TOOL_NAME + "_v1",
        description: str = TEXT_EDITOR_INSERT_TOOL_FN.metadata.description,
    ) -> ToolSpec:
        async def insert(
            path: str,
            insert_line: int,
            new_str: str,
        ) -> list[ResultContentBlockType]:
            session = await self._session(config)
            result = await session.insert(path, insert_line, new_str)
            if not result.success:
                raise RuntimeError(result.error or "Unable to insert text")
            output = _truncated(
                result.output, self._settings.code_execution.max_output_bytes
            )
            inserted_lines = len(new_str.splitlines())
            return [
                TextEditorCodeExecutionStrReplaceResultBlock(
                    old_start=insert_line,
                    new_start=insert_line,
                    new_lines=inserted_lines,
                    lines=[output],
                )
            ]

        return ToolSpec.from_defaults(
            name=name,
            type=type,
            runtime="server",
            event_adapter=TextEditorCodeExecutionEventAdapter,

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Check result.error / server logs for the underlying session failure before the generic message was substituted
  2. Verify the target path exists and the tool process has read/write permission on it
  3. Validate insert_line against the current file (0 <= insert_line <= line_count) before invoking the tool
  4. Re-read the file (view tool) to refresh line numbers, then retry the insert

Example fix

# before
result = await session.insert(path, insert_line, new_str)
# after
content = await session.view(path, 0)
max_line = len(content.output.splitlines())
if not (0 <= insert_line <= max_line):
    raise ValueError(f"insert_line {insert_line} out of range 0..{max_line}")
result = await session.insert(path, insert_line, new_str)
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path

p = Path(path)
assert p.is_file(), f"{path} is not an existing file"
line_count = len(p.read_text().splitlines())
assert 0 <= insert_line <= line_count, f"insert_line {insert_line} out of range 0..{line_count}"

Try / catch

try:
    blocks = await insert(path, insert_line, new_str)
except RuntimeError as e:
    if "Unable to insert text" in str(e):
        # re-view the file, correct path/line, retry once with corrected args
        raise
    raise

Prevention

When it happens

Trigger: Calling the insert tool (TEXT_EDITOR_INSERT_TOOL_NAME) with a path that does not exist or is not readable/writable by the sandboxed session, an insert_line outside the file's line range, or a session backend (e.g. code-execution sandbox) that failed to apply the edit and set result.success=False with result.error empty.

Common situations: Agent/LLM hallucinating a file path or line number; permission mismatch between the tool process and the file; file modified concurrently so the session's view is stale; sandbox restrictions blocking writes.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/9abbefb704854e34. Report an issue: GitHub.