Skip to content

Project-memory loader panics (String::truncate) on multibyte files — crashes every project-bound chat turn #46

@TYRMars

Description

@TYRMars

Summary

read_limited() / the memory-management view use String::truncate(max_bytes), which panics when max_bytes does not fall on a UTF-8 char boundary. The project-memory files are markdown that routinely contains CJK (the repo itself stores zh-CN project memory), so an oversized memory file with a multi-byte char straddling the cap crashes the request.

Details

  • crates/harness-server/src/project_memory.rs:499-505:
    fn read_limited(path: &Path, max_bytes: usize) -> std::io::Result<String> {
        let mut s = std::fs::read_to_string(path)?;
        if s.len() > max_bytes {
            s.truncate(max_bytes);   // panics if max_bytes is not a char boundary
            ...
  • Same pattern in the management view at project_memory.rs:158-161 (truncated.truncate(MAX_MANAGED_FILE_BYTES)).

read_limited is the hot path: it's called by load_project_memory_prompt (project_memory.rs:93-96) with config.max_bytes (index) and MAX_PROMPT_FILE_BYTES = 12_000 (kanban/calendar). load_project_memory_prompt runs via the project binder on every project-bound chat turn, so a single oversized CJK-heavy memory file takes down the turn; the line-158 variant takes down the memory-management REST view.

String::truncate documents: "Panics if new_len does not lie on a char boundary."

Impact

A reproducible panic on a normal data condition (a memory file just over the cap), reachable on the main chat path. Severity: high.

Suggested fix

Truncate to the largest char boundary <= max_bytes (e.g. str::floor_char_boundary, or walk back from max_bytes while !s.is_char_boundary(i)), then push the warning suffix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions