fixing-bugs · git:20260619.c43368b · 2026-06-19 · sha256 15e8de2001ba88c0

fixing-bugs git:20260619.c43368bA

Immutable. This exact content is served forever at /api/v1/blob/15e8de2001ba88c0.

---
name: fixing-bugs
description: Fix a Langflow bug using strict TDD — UNDERSTAND → REPRODUCE (RED) → VERIFY RED → FIX → VERIFY GREEN → VALIDATE → REFACTOR — with Langflow hotspot awareness (lfx vs langflow-base split, dynamic component discovery, expand-contract Alembic migrations, pre-commit must invoke uv run git commit). Use when the user reports a bug in Langflow, mentions Sentry/error/regression, pastes a stack trace, or asks to fix something. Bugs require a failing test that proves the bug existed before any code change. For building new features use developing-features-tdd; for non-TDD code work use developing-features.
license: MIT
---

# Fixing Bugs

Never fix a bug before proving it exists with a failing test. The fix is only valid if a test transitions from RED (failing) to GREEN (passing).

## Read first (always)

List `learnings/` and read every file relevant to the current bug. Project-specific test conventions, framework quirks, recurring bug patterns, or hot zones live there and override the defaults in this SKILL.md. If a learning conflicts with this file, **the learning wins** — mention it to the user.

## Tradeoff — when to apply, when to lighten up

Apply the full cycle for **any defect in production code** the user is reporting (Sentry alert, support ticket, "this broke", regression). The discipline pays off because the test becomes a permanent sentinel against the same bug returning.

Lighten the formality only when fixing a typo, a build script, or a one-off script the user explicitly labels as throwaway. Even then, run the test suite afterwards.

## The cycle (strict order)

```
1. UNDERSTAND   →  Read the bug report; identify expected vs actual; locate the OS/platform
2. REPRODUCE    →  Write a failing test that triggers the EXACT error path
3. VERIFY RED   →  Run the test; it MUST fail for the reason in the bug report
4. FIX          →  Write the MINIMUM code change to make the test pass
5. VERIFY GREEN →  Run the same test; it MUST now pass
6. VALIDATE     →  Run the FULL suite (CI matrix if platform-suspect); nothing else breaks
7. REFACTOR     →  Optional; only if the fix introduced duplication. Tests stay GREEN
```

If you skip steps or change the order, the fix is invalid. Full per-phase detail in `references/cycle.md`.

## Phase 1 — UNDERSTAND

Decompose the bug report:

```
GIVEN:    <precondition / initial state>
WHEN:     <action that triggers the bug>
THEN:     <what actually happens — the bug>
EXPECTED: <what should happen — the fix target>
```

If you can't extract all four → **ask for clarification**, don't guess.

**Identify the platform dimension.** Bug reports rarely state the OS. Check user agent, Sentry tags, container image, support metadata. Bugs in the following areas are platform-suspect by default — filesystem operations, text encoding / line endings, subprocess / shell, temp / config dir resolution, process signals, networking. If the bug is platform-suspect, **the test must run on the affected OS** in Phase 3.

**Pick an investigation technique** (full list in `references/investigation.md`):

| Technique                | When                                                        |
|--------------------------|-------------------------------------------------------------|
| Read error logs          | Always start here                                            |
| Reproduce locally        | Always — if you can't reproduce, you can't fix              |
| `git bisect`             | The bug is a regression and you don't know which commit broke it |
| `git log` / `git blame`  | You need the history of the affected code                    |
| Debugger / breakpoints   | You need to inspect runtime state                            |
| 5 Whys                   | Bug is recurring or the surface cause looks too simple       |

Do **not** open the editor and start changing things. Systematic investigation beats trial-and-error.

## Phase 2 — REPRODUCE

The test is the proof the bug exists. No test = no proof = no fix.

The test must:

1. Reproduce the exact scenario from the bug report.
2. Exercise the **exact** error path — not a similar one. If the report says `GeneratorExit`, your test triggers `GeneratorExit`, not `CancelledError`.
3. Assert the **expected** behavior, not the buggy behavior.
4. Fail before the fix.
5. Pass after the fix.
6. Fail with a message consistent with the bug report.

**Naming:** `should_[expected_behavior]_when_[condition_that_triggered_bug]`. Examples and full quality rules in `references/cycle.md`.

→ verify: the test exercises the precise code path described in the stack trace or repro steps, and the failure message names the bug.

## Phase 3 — VERIFY RED

Run the test. It MUST fail. Document:

```
TEST: <name>
STATUS: FAILED
ERROR: <actual error or assertion message>
MATCHES BUG REPORT: Yes — <one-line tie-back to the report>
```

If the test passes before the fix, one of three things is true:

- The bug isn't reproducible with your scenario → revisit Phase 1.
- The assertions are wrong → revisit Phase 2.
- The bug is already fixed in the current code → confirm against the latest and close the ticket.

If the test fails for a **different** reason than the report:

- Setup error in Arrange → fix the fixture.
- The bug has a different root cause → revisit Phase 1.
- Mocks or fakes are wrong → check them.

Don't proceed to FIX until the failure reason is clean.

## Phase 4 — FIX

Change the **minimum** code necessary. Do **not** refactor, optimize, or add features in the same diff.

**Root cause analysis** (write this down before coding):

```
ROOT CAUSE:
  File: <path>
  Function: <name>
  Line: <number>
  Issue: <one-line explanation of why the bug occurs>
  Fix: <one-line description of the minimum change>
```

**Follow existing codebase patterns.** Before writing the fix, search for similar error handling or patterns already established. If prior art exists (e.g., another function already handles the same exception type), follow that pattern.

**Pre-existing issues discovered during the fix:**

| Situation                                                                            | Action                                                          |
|--------------------------------------------------------------------------------------|-----------------------------------------------------------------|
| Pre-existing issue is in the lines you're touching and trivial to fix                | Fix it in the same PR, note "pre-existing fix" in description   |
| Pre-existing issue is adjacent and involves moderate refactoring                     | Separate commit in the same PR, or a follow-up ticket           |
| Pre-existing issue is in a different area                                            | Separate ticket — don't touch it here                           |

The test: does fixing this pre-existing issue make my bug fix **safer or easier to review**? If yes, include it (separate commit). If no, ticket it.

**Scope rules:**

| Allowed                                                              | Not allowed                                            |
|----------------------------------------------------------------------|--------------------------------------------------------|
| Fix the root cause of the reported bug                               | Refactor the entire module                             |
| Add a guard clause for the edge case                                 | Rewrite the function "for clarity"                     |
| Correct a conditional logic error                                    | Change the API contract                                |
| Fix an off-by-one error                                              | Add new parameters or endpoints                        |
| Handle a missing null check                                          | Reorganize the file structure                          |
| Fix a pre-existing issue in the lines you're touching (note in PR)   | Fix pre-existing issues in unrelated areas             |

## Phase 5 — VERIFY GREEN

Run the same test from Phase 2. It MUST now pass. Document:

```
TEST: <name>
STATUS: PASSED
BEFORE FIX: <failure message>
AFTER FIX: <pass>
ROOT CAUSE: <one-line>
```

If it still fails, the fix is wrong or incomplete. Don't proceed to VALIDATE.

## Phase 6 — VALIDATE

Run the **full** test suite. All tests must pass.

If a pre-existing test breaks:

1. **Analyze** — is the breaking test correct, or was it asserting the buggy behavior as correct?
2. **If the test was wrong** (it locked in the bug) → fix the test in the same PR, document why.
3. **If the test was right** → your fix has a side effect. Return to Phase 4.
4. **Never delete a failing test** to make CI green.

**Cross-platform validation.** If the bug was platform-suspect, the test must be green on **every supported OS**, not just yours. Run through CI on the affected OS before declaring done. If the suite didn't previously run on that OS, extending the CI matrix is part of **this** fix, not "a follow-up PR". See `ensuring-cross-platform` skill.

**Regression checklist:**

- [ ] New bug-fix test passes (GREEN).
- [ ] All existing unit tests pass.
- [ ] All existing integration tests pass (if applicable).
- [ ] No new warnings.
- [ ] Linter, formatter, type checker pass.
- [ ] CI matrix passes on every supported OS.

## Phase 7 — REFACTOR (optional)

Only if the fix introduced duplication or reduced clarity. Tests must stay GREEN. Small steps. Re-run tests after each. Separate commit from the fix.

## The bug-fix test is permanent

The test you wrote in Phase 2 is **the permanent sentinel against this bug returning**. Recurring bugs are one of the most common problems in software. Without a test, a future refactor can silently reintroduce the exact same defect.

- Never delete a bug-fix test unless the feature it tests is removed.
- Bug-fix tests must run in CI/CD on every build and PR.
- If a bug comes back, either the test was deleted, the test was too narrow, or someone overrode it. Investigate, don't just re-fix.

## Logging quality in bug fixes

A bug fix often adds log statements (error handlers, fallback paths, disconnection events). These logs **must** meet the same quality bar as any other production code.

- **Correlation context is mandatory.** Every new log includes IDs (request, conversation, user, resource) that let a future investigator trace the event.
- **Event names are unique.** Two different error conditions must NOT log the same event name — collisions break filtering in Sentry/CloudWatch/Datadog.
- **Follow the codebase convention.** Check the existing logging style in the file before adding a new statement.
- **Platform context for platform bugs.** If the root cause was OS-specific, include `platform=sys.platform` (or equivalent) in the log.

Full guidance in `developing-features/references/observability.md`.

## Code quality still applies

A bug fix does NOT exempt you from project standards. All `developing-features` rules apply: no PII in logs, no secrets, file structure hard limits, strong typing, no silent failures, linters/formatters pass.

If your fix would violate a code quality rule → find a different approach.

## Final step: capture a learning

Before closing the task, ask: *did I encounter a bug pattern, framework quirk, OS trap, or recurring shape that wasn't in this SKILL.md or `references/`?* If yes, append a `learnings/YYYY-MM-DD-slug.md`. If no, skip.

Pay particular attention to **bug clusters**: if the same kind of bug keeps recurring (off-by-one, null pointer, timezone, encoding), the learning should describe the **systemic root cause and where to prevent it**, not just this instance.

## Output format

1. **Root cause analysis** — WHERE, WHY, WHAT (concise, 3–5 lines). Include 5 Whys for complex or recurring bugs.
2. **Characterization tests** (if applicable) — capture existing behavior as a safety net.
3. **Failing test** — the test that reproduces the bug (RED).
4. **Fix** — the minimum code change.
5. **Passing test** — confirmation the same test now passes (GREEN).
6. **Regression check** — confirmation all existing tests pass.
7. **Brief explanation** — what was changed and why, in 2–3 bullets.
8. **Investigation notes** (complex bugs) — what was investigated and ruled out.

## See also

- `references/cycle.md` — phase-by-phase detail and examples (test naming, AAA structure, exact-error-path rule).
- `references/investigation.md` — `git bisect` automation, 5 Whys, debugging journal, bug clustering.
- `references/checklist.md` — full bug-fix checklist + commit format + PR description rules + edge cases (multiple bugs, untested code, integration-only, regressions).
- `developing-features` skill — code quality / SOLID / file structure / security / observability rules that apply during the fix.
- `developing-features-tdd` skill — broader TDD reference; bugs are TDD's narrow case.
- `ensuring-cross-platform` skill — required when the bug is platform-suspect.
- `learnings/` — project-specific bug patterns, hot zones, recurring traps accumulated over time.