Skip to content

[BUG] [v0.1.0] WriteFileHandler content_preview panics on multi-byte UTF-8 due to byte-index slicing (file_ops.rs:240) #167

@climax-dev-1

Description

@climax-dev-1

Bug Description

WriteFileHandler::execute() in cortex-engine/src/tools/handlers/file_ops.rs uses byte-index slicing (args.content[..500]) to create a content preview for tool metadata. This panics at runtime if the written content contains multi-byte UTF-8 characters and byte position 500 falls inside a multi-byte character.

Location

src/cortex-engine/src/tools/handlers/file_ops.rs, lines 239–240

Root Cause

let content_preview = if args.content.len() > 500 {
    args.content[..500].to_string()  // BUG: byte-index slice panics on multi-byte UTF-8
} else {
    args.content.clone()
};

args.content.len() returns byte length. When the content contains multi-byte UTF-8 characters (CJK, emoji, accented chars), byte 500 may fall in the middle of a character, causing a panic:

thread panicked at byte index 500 is not a char boundary

Reproduction

// Each CJK character is 3 bytes. 167 chars = 501 bytes.
// content.len() = 501 > 500, so we try content[..500]
// Byte 500 is in the middle of the 167th character → PANIC
let content = "日".repeat(167);

Fix

let content_preview = if args.content.len() > 500 {
    args.content.chars().take(500).collect::<String>()
} else {
    args.content.clone()
};

Impact

When the Write tool is used to create or overwrite a file containing multi-byte UTF-8 content (internationalized text, emoji, documentation with accented characters), the tool handler panics. This crashes the tool execution and breaks the agentic loop. Unlike the similar bug in generate_diff_preview (issue #165) which affects the TUI preview, this bug is in the actual tool execution path — it prevents the Write tool from completing successfully.

Note

This is distinct from issue #165 which covers generate_diff_preview() in streaming.rs. This bug is in the tool handler itself (file_ops.rs), a different file and different code path. The file write itself succeeds (line 227), but the metadata construction panics afterward, so the tool result is never returned to the LLM.

Version

v0.1.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions