[BUG] Edit tool incorrectly inserts (MISSING) placeholder after percent (%) characters when processing code

Resolved 💬 2 comments Opened Aug 20, 2025 by a5223594 Closed Aug 21, 2025

Environment

  • Platform (select one):
  • [ ] Anthropic API
  • [ * ] AWS Bedrock
  • [ ] Google Vertex AI
  • [ ] Other: <!-- specify -->
  • Claude CLI version: v1.0.85
  • Operating System: Windows 11
  • Terminal: Terminal App Powershell

Bug Description

There is a consistent bug in the Edit tool where a (MISSING) placeholder is incorrectly inserted immediately after any percent sign (%) in the code being edited or generated. This issue seems to occur during the process of writing the code to the final output/file, as the underlying data stream from the model (Claude) does not contain these placeholders.

The problem appears to be related to string formatting or a replacement logic that misinterprets the % symbol as a specifier, causing the insertion of the erroneous (MISSING) text.

Steps to Reproduce

  1. Use the Edit tool functionality.
  2. Provide a prompt that will generate code containing the percent (%) symbol. A good example is requesting CSS code for animations or properties using percentage units.
  3. Example prompt: 写个样式,展示呼吸灯效果 (Chinese for: "Write a style to show a breathing light effect").
  4. Observe the code block generated by the Edit tool.

Expected Behavior

The code should be generated correctly without any extra placeholders. For example, CSS properties and keyframe selectors should be rendered as standard:

/* Expected Correct CSS */
.breathing-light {
    width: 100px;
    height: 100px;
    border-radius: 50%; /* << Correct */
    background: radial-gradient(circle, #00ff88, #00cc66);
    animation: breathing 2s ease-in-out infinite;
    box-shadow: 0 0 20px #00ff88;
}
@keyframes breathing {
    0%, 100% { /* << Correct */
        opacity: 0.3;
        transform: scale(0.9);
        box-shadow: 0 0 10px #00ff88;
    }
    50% { /* << Correct */
        opacity: 1;
        transform: scale(1.1);
        box-shadow: 0 0 40px #00ff88, 0 0 60px #00ff88;
    }
}

Actual Behavior

The Edit tool incorrectly inserts a (MISSING) placeholder after every % character in the generated code block:

/* Actual Buggy Output */
.breathing-light {
    width: 100px;
    height: 100px;
    border-radius: 50%!(MISSING)  /* << BUG */
    background: radial-gradient(circle, #00ff88, #00cc66);
    animation: breathing 2s ease-in-out infinite;
    box-shadow: 0 0 20px #00ff88;
}
@keyframes breathing {
    0%!(MISSING), 100%!{(MISSING)  /* << BUG */
        opacity: 0.3;
        transform: scale(0.9);
        box-shadow: 0 0 10px #00ff88;
    }
    50%!{(MISSING)  /* << BUG */
        opacity: 1;
        transform: scale(1.1);
        box-shadow: 0 0 40px #00ff88, 0 0 60px #00ff88;
    }
}

Additional Context

Supporting Logs and Analysis

Debug logs show that the data stream received from the Claude model is correct and does not contain the (MISSING) placeholder. This strongly suggests the issue is introduced locally by the Edit tool itself, likely during a post-processing or file-writing step.

2025/08/20 11:20:13 [DEBUG] Send to claude: {"delta":{"text":"border-radius: 50%;\n  box-shadow: 0 0 10px #2ecc71;\n  animation:","type":"text_delta"},"index":0,"type":"content_block_delta"}
2025/08/20 11:20:13 [DEBUG] Send to claude: {"delta":{"text":"\n  0%, 100% {\n    box-shadow: 0 0 10px #2ecc71;\n    transform: scale(","type":"text_delta"},"index":0,"type":"content_block_delta"}

As seen in the logs, border-radius: 50%; and 0%, 100% { are correctly formed in the streaming delta.

Hypothesis

The root cause is likely a string replacement or formatting function within the Edit tool's code that handles the incoming text from the model. This function probably uses the % character as a format specifier (like in printf or Python's older % formatting). When it encounters a literal % in the code, it fails to find a corresponding value to substitute, resulting in an error or a default placeholder like (MISSING). The - character is also present, which might indicate a %! combination is being misinterpreted.

View original on GitHub ↗

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