Intro
You’re using ChatGPT or Claude to speed up development. Good.
Then suddenly: your migrations are broken.
AI tools love editing files they shouldn’t touch, especially:
- SQL migration scripts
- EF Core migration files
- Schema snapshots
This is dangerous. One wrong change can corrupt your database history.
Recognize migration files
EF Core migrations
Typical structure:
/Migrations/
20240101120000_InitialCreate.cs
20240102130000_AddUsers.cs
MyDbContextModelSnapshot.cs
Example:
public partial class AddUsers : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(nullable: false)
});
}
}
SQL migrations
/db/migrations/
V001__init.sql
V002__add_users.sql
Example:
CREATE TABLE Users (
Id INT PRIMARY KEY
);
Key indicators
- Timestamp or version prefix
- Sequential naming
- Contains schema changes only
- Stored in a dedicated folder
Understand the risk
WRONG (AI rewriting history)
AI might do this:
// Modified existing migration (BAD)
migrationBuilder.DropTable("Users");
migrationBuilder.CreateTable("Customers");
or:
-- Edited old migration (BAD)
ALTER TABLE Users RENAME TO Customers;
This breaks every environment except fresh ones. This is extremely dangerous if your AI does not recognize them.
CORRECT (append-only)
Always create a new migration:
// New migration
migrationBuilder.RenameTable(
name: "Users",
newName: "Customers");
Step 3: Lock migration files from Claude AI editing
Explicit blocking of editing
We will create 2 new files. These files will instruct that CALUDE is not allowed to modify existing files. What we actually want to achieve is a way to keep appending the files.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/block-migration-edits.sh\""
}
]
}
]
}
}
#!/usr/bin/env bash
# PreToolUse guard: block AI agents from hand-editing EF Core migration files.
#
# EF Core migrations are an append-only ledger: existing migrations may already
# have run against real databases, so editing them silently breaks both clean
# and existing installs (see CLAUDE.md). New migrations must always be created
# with `dotnet ef migrations add <Name>`, which writes files via the dotnet CLI
# (Bash) rather than the Edit/Write tools — so this guard does not block it.
#
# Reads the PreToolUse payload on stdin and denies Edit/Write/MultiEdit when the
# target path is inside a Migrations directory.
input="$(cat)"
file_path="$(printf '%s' "$input" | python3 -c 'import json,sys
try:
data = json.load(sys.stdin)
except Exception:
print("")
sys.exit(0)
ti = data.get("tool_input") or {}
print(ti.get("file_path") or ti.get("path") or "")' 2>/dev/null)"
case "$file_path" in
*/Migrations/*|*/Migrations)
cat <<'JSON'
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Editing EF Core migration files is blocked. Migrations are append-only and may already have run against real databases. Never modify an existing migration; create a new one with: dotnet ef migrations add <Name> (and adjust the data model instead)."}}
JSON
exit 0
;;
esac
exit 0
How do we proceed?
If you are trying to modify any large project that uses migrations or scripts that reach out to external systems, such as databases, always check if these files exist and identify them.
If you are lazy like me try to prompt for them often.
Identify all migration files. Generate a list of all migration files in this project. Implement a safe way to block editing by AI agents and only allow append only on any migration files.
Conclusion
AI tools are useful, but unsafe by default around migrations.
Happy coding!
Top comments (0)