[BUG] File Editing Issue: Read/Write Cycle Trap with External File Locks

Resolved 💬 3 comments Opened Sep 17, 2025 by 10kclubguy Closed Sep 25, 2025

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Summary

Claude Code's Read/Write safety mechanism gets trapped in an infinite cycle when external processes (like
Flutter's build_runner) lock files, making file editing impossible in certain development environments.

Environment

  • OS: Windows 11
  • Claude Code Version: Latest (as of 2025-09-17)
  • Project Type: Flutter application with build_runner code generation
  • File Type: Dart source files (.dart)

Problem Description

Expected Behavior

  1. Read file with Read tool
  2. Write file with Write tool
  3. File is successfully updated

Actual Behavior

  1. Read file with Read tool ✅
  2. Write file with Write tool ❌ (File has been unexpectedly modified error)
  3. Try write again ❌ (File has not been read yet. Read it first before writing to it. error)
  4. Read file again ✅
  5. Write fails again ❌ (external process still locking)
  6. Infinite cycle - cannot edit file

Root Cause Analysis

Claude Code's Safety Mechanism

  • Requires reading file before writing (prevents accidental overwrites)
  • Each Read operation is "consumed" by one Write attempt
  • If Write fails, the read state is lost and requires fresh Read

External File Locking

Flutter's build_runner watches files for code generation:

  • Monitors 50+ data model files continuously
  • Locks files during auto-regeneration of .g.dart files
  • Restarts automatically even after being killed

The Trap

When external processes lock files, Claude Code's safety mechanism creates an infinite loop:
Read file ✅ → Write fails (external lock) ❌ → Read consumed → Try write → "File not read" ❌ → Read again ✅ →
Write fails ❌ → INFINITE CYCLE

Reproduction Steps

  1. Set up Flutter project with build_runner:

flutter create test_app
cd test_app
# Add json_annotation and build_runner dependencies
flutter pub get
flutter pub run build_runner watch

  1. Create a data model file with @JsonSerializable annotation
  2. Try to edit the file with Claude Code:
  • Use Read tool to read the file
  • Use Write tool to write changes
  • Observe the error cycle
  1. Verify external lock:

# build_runner will be watching and locking the file
tasklist | findstr dart
# Shows multiple dart.exe processes including build_runner

Error Messages

First Write Attempt

File has been unexpectedly modified. Read it again before attempting to write it.

Subsequent Write Attempts

File has not been read yet. Read it first before writing to it.

Current Workarounds

  1. Stop External Processes (Temporary)

flutter pub run build_runner clean
powershell "Stop-Process -Name dart -Force"
Issue: build_runner restarts automatically

  1. Reset Claude Code Tracking

rm file.dart && touch file.dart
# This resets Claude Code's internal file tracking

  1. Use Alternative Tools

# Use sed for quick text replacements
sed -i 's/old_pattern/new_pattern/' file.dart

Impact

High Impact for Flutter Developers

  • build_runner is essential for Flutter code generation
  • Cannot disable permanently - needed for JSON serialization, database models, etc.
  • Affects daily development workflow - common editing tasks become impossible

Affected File Types

  • Data models with @JsonSerializable
  • Database entities with @HiveType
  • Any file with part '*.g.dart' declarations
  • Files monitored by code generation tools

What Should Happen?

Proposed Solutions

Option 1: Preserve Read State on External Lock

When Write fails due to external file lock, preserve the read state instead of consuming it.

Option 2: Auto-Retry with Backoff

Automatically retry failed writes with exponential backoff when external locks are detected.

Option 3: External Lock Detection

Detect when file failures are due to external locks vs. actual file changes, and handle differently.

Option 4: Grace Period

Allow a grace period where the same read can be used for multiple write attempts within a short timeframe.

Technical Details

File Lock Detection

# The file itself isn't locked (no file handle locks)
lsof file.dart # Returns empty

# But build_runner processes are running
tasklist | findstr dart
# Shows: dart.exe processes using 200MB+ (build_runner)

Claude Code Internal State

  • Maintains internal tracking of which files have been read
  • Resets this state after each write attempt (successful or failed)
  • No distinction between failure types (external lock vs. file change)

Additional Context

Why This Matters

  • Flutter ecosystem standard: build_runner is the official code generation tool
  • Cannot be avoided: Required for modern Flutter development patterns
  • Breaks core workflow: File editing is fundamental to coding assistance

Frequency

  • Every Flutter project using code generation
  • Daily occurrence for active Flutter developers
  • Blocks productivity during development sessions

Workaround Effectiveness

| Method | Effectiveness | Duration | Issues |
|---------------------|---------------|-----------|----------------------|
| Stop build_runner | ✅ Works | Temporary | Auto-restarts |
| Reset file tracking | ✅ Works | One-time | Must repeat per file |
| Use sed/bash | ⚠️ Limited | Permanent | No syntax validation |

Request

Please consider implementing one of the proposed solutions to handle external file locks gracefully. This would
significantly improve the Flutter development experience with Claude Code.

Error Messages/Logs

Steps to Reproduce

Steps to Reproduce

  1. Create Flutter project with build_runner:

```bash
flutter create test_project
cd test_project

  1. Add dependencies to pubspec.yaml:

dependencies:
json_annotation: ^4.8.1

dev_dependencies:
build_runner: ^2.4.7
json_serializable: ^6.7.1

  1. Install dependencies:

flutter pub get

  1. Create a data model file (lib/models/test_model.dart):

import 'package:json_annotation/json_annotation.dart';

part 'test_model.g.dart';

@JsonSerializable()
class TestModel {
final String name;
final int value;

TestModel({required this.name, required this.value});

factory TestModel.fromJson(Map<String, dynamic> json) => _$TestModelFromJson(json);
Map<String, dynamic> toJson() => _$TestModelToJson(this);
}

  1. Start build_runner watching:

flutter pub run build_runner watch

  1. Try to edit the file with Claude Code:
  • Use Read tool: Read lib/models/test_model.dart
  • Use Write tool to modify the file
  • Observe the error cycle

Expected Result

File should be edited successfully.

Actual Result

  • First write: File has been unexpectedly modified. Read it again before attempting to write it.
  • Subsequent writes: File has not been read yet. Read it first before writing to it.
  • Cannot edit file despite multiple read attempts.

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

Claude Code v1.0.113

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

_No response_

View original on GitHub ↗

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