mcpbeat

Ecto Constraint Debug

oliver-kriska/claude-elixir-phoenix-ecto-constraint-debug

Debug Ecto constraint violations - trace triggers, check migrations, find duplicate data. Use when seeing unique_constraint, foreign_key_constraint, or check_constraint errors.

2k tokens
context cost
the whole folder, loaded on every use
2
files
instructions only
0
copies elsewhere
how many repositories repackaged it
514
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/oliver-kriska/claude-elixir-phoenix --skill ecto-constraint-debug

What comes with it

5 253 bytes besides the instruction
references/constraint-patterns.md

The instruction itself

11 sections, as written by the author

Ecto Constraint Debugging

> Ash projects: Ash surfaces DB constraints through its own error DSL. Use the ash-framework skill — mix usage_rules.search_docs "constraint" -p ash_postgres.

Systematic approach to diagnosing constraint violations. Load when you see Ecto.ConstraintError, unique_constraint, foreign_key_constraint, or constraint-related changeset errors.

Iron Laws

  • READ THE CONSTRAINT NAME — The constraint name (e.g., links_url_index) tells you exactly which index/constraint failed. Parse it from the error message first
  • CHECK MIGRATION BEFORE CODE — Verify the constraint definition in priv/repo/migrations/ matches what the schema expects
  • TRACE ALL INSERT PATHS — Find every code path that inserts into the constrained table. The bug is often in a path you didn't consider
  • RACE CONDITION UNTIL PROVEN OTHERWISE — If validation passes but constraint fails, assume concurrent inserts until you prove a single-request cause

Step-by-Step Debugging

Step 1: Parse the Error

Extract from the error message:

  • Constraint name (e.g., users_email_index)
  • Table name (e.g., users)
  • Operation (insert, update, or delete)
  • Conflicting values (if available in logs)

Step 2: Find the Migration

Use Grep to search for the constraint name in priv/repo/migrations/. Also check for create unique_index, create index, add constraint.

Verify: Does the migration constraint match the schema's unique_constraint/3 or foreign_key_constraint/3 call?

Step 3: Find the Schema

Use Grep to find constraint handling in changesets (unique_constraint, foreign_key_constraint, check_constraint) in lib/.

Step 4: Trace Insert Paths

Find ALL callers that insert/update this schema:

Use Grep to find all insert/update paths (Repo.insert, Repo.update, Repo.insert_all, cast_assoc) in lib/.

Step 5: Identify the Cause

| Symptom | Likely Cause | Fix Pattern |

|---------|-------------|-------------|

| Same user triggers twice | Race condition (double-click, retry) | Upsert with on_conflict |

| Multiple parents share child | cast_assoc doesn't dedup across changesets | Dedup before building changesets |

| Concurrent API requests | Missing transaction isolation | Wrap in Repo.transaction or use upsert |

| Migration added constraint to existing data | Data violates new constraint | Backfill or clean data first |

Step 6: Apply Fix

See references/constraint-patterns.md for detailed fix patterns.

Quick Fixes by Constraint Type

Unique violation → Upsert: Repo.insert(changeset, on_conflict: :replace_all, conflict_target: [:field])

Foreign key violation → Check: Does the referenced record exist? Was it deleted concurrently?

Check constraint → Validate: Does the value satisfy the constraint condition?

References

  • references/constraint-patterns.md - Detailed patterns for each constraint type

How to use it

Copy the folder

Take oliver-kriska/claude-elixir-phoenix-ecto-constraint-debug from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.