[Bug] UTF-8 String Slicing Panic with Multi-byte Characters in Skill Descriptions

Resolved 💬 3 comments Opened Dec 20, 2025 by GoosLab Closed Feb 14, 2026

Bug Report: UTF-8 String Slicing Panic with Korean Characters

Summary

Claude Code CLI crashes with a Rust panic when processing strings containing Korean (or other multi-byte UTF-8) characters. The panic occurs during string slicing operations that use byte indices instead of character boundaries.

Environment

  • Claude Code Version: Latest (as of 2025-12-20)
  • OS: macOS Darwin 25.2.0
  • Platform: darwin (Apple Silicon)
  • Rust Version: Unknown (compiled binary)

Error Message

thread '<unnamed>' (5025078) panicked at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library/core/src/str/mod.rs:833:21:
byte index 6 is not a char boundary; it is inside '의' (bytes 4..7) of `-ADK의 moai-worktree 스킬은 Git Worktree를 `
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5, aborting
[1]    70176 abort      claude --dangerously-skip-permissions -d -r

Steps to Reproduce

  1. Create a skill or command with Korean text in the description
  2. Example text: -ADK의 moai-worktree 스킬은 Git Worktree를...
  3. Run Claude Code CLI with the skill loaded
  4. CLI crashes with the above panic

Root Cause Analysis

Technical Details

The panic occurs because the code attempts to slice a UTF-8 string at byte index 6, which falls inside a multi-byte Korean character.

UTF-8 Byte Structure:

| Position | Bytes | Character |
|----------|-------|-----------|
| 0 | 1 byte | - |
| 1 | 1 byte | A |
| 2 | 1 byte | D |
| 3 | 1 byte | K |
| 4-6 | 3 bytes | (Korean) |
| 7 | 1 byte | (space) |

The code tries to slice at byte index 6, which is the middle of the Korean character (occupying bytes 4, 5, 6). In Rust, slicing a &str at a non-character-boundary causes a panic.

Problematic Pattern

// This pattern causes the panic:
let slice = &text[0..6];  // Panics if byte 6 is inside a multi-byte char

// Safe alternatives:
// 1. Use char_indices()
let boundary = text.char_indices().nth(n).map(|(i, _)| i).unwrap_or(text.len());
let slice = &text[0..boundary];

// 2. Use floor_char_boundary() (Rust 1.73+)
let safe_index = text.floor_char_boundary(6);
let slice = &text[0..safe_index];

Impact

  • Severity: High (causes complete CLI crash)
  • Scope: Any user with non-ASCII characters in skill descriptions, command outputs, or file paths
  • Affected Languages: Korean, Japanese, Chinese, Emoji, and any multi-byte UTF-8 characters

Suggested Fix

  1. Replace all byte-based string slicing with character-boundary-aware methods
  2. Use str::floor_char_boundary() (Rust 1.73+) or char_indices() for safe slicing
  3. Add unit tests with multi-byte UTF-8 strings to prevent regression

Workaround

Users can temporarily avoid this issue by:

  • Using only ASCII characters in skill descriptions
  • Avoiding Korean/Japanese/Chinese text in metadata fields

Additional Context

This occurred while using MoAI-ADK project with Korean skill descriptions. The skill system loads YAML files containing Korean text, which triggers the panic during display or processing.

---

Reported by: GOOS
Date: 2025-12-20
Project: MoAI-ADK (https://github.com/moai-adk)

Environment Info

  • Platform: darwin
  • Terminal: WarpTerminal
  • Version: 2.0.74
  • Feedback ID: cd408228-6ebe-4f3a-a900-50675b4d3c37

Errors

[{"error":"Error: NON-FATAL: Lock acquisition failed for /Users/goos/.local/share/claude/versions/2.0.74 (expected in multi-process scenarios)\n    at XZR (/$bunfs/root/claude:2430:2165)\n    at bUA (/$bunfs/root/claude:2430:1885)\n    at processTicksAndRejections

Note: Error logs were truncated.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗