Code Without Bugs and Without Nerves: 14 Prompts for Debugging, Testing, and Hunting Memory Leaks in JavaScript and TypeScript

Why your debugger is not enough anymore

Every JavaScript developer knows the ritual: a bug appears in production, you open DevTools, set a breakpoint, and start the slow dance of stepping through minified code. Meanwhile, TypeScript's type system catches a whole class of errors at compile time — but it cannot catch a race condition in an async queue, a closure that pins a 50 MB buffer, or a Jest mock that silently returns undefined.

This roundup is a collection of prompts I actually use when ChatGPT becomes my pair programmer for debugging and testing. Each prompt is battle-tested: it has an input example, an expected output, and a note on when to apply it. No fluff — just paste your code and get a fix, a test, or a hypothesis.

How to use: Copy the prompt, replace the placeholders (in ALL_CAPS), and paste your code. The more context you give (Node version, browser, framework), the sharper the answer. All examples target Node.js 20+, TypeScript 5.x, Jest 29, and Vitest 1.x — current as of October 2026.


1. Reproduce the bug from a stack trace

When to use: You have a TypeError: Cannot read properties of undefined and a stack trace full of node_modules. The goal is to find the first line in your code that triggered it.

Prompt:

You are a senior Node.js debugger. Here is a stack trace and the relevant source files.
1. Identify the first frame that belongs to my code (not node_modules).
2. Explain in plain English what value was undefined and why.
3. Give the minimal code change to fix it.
4. Suggest one assertion I can add to catch this earlier.

STACK TRACE:
PASTE_TRACE

SOURCE:
PASTE_FILES

Example input: a trace ending with at getUser (/app/src/api.ts:42:18) and user.profile.name.

Expected result: The model points to getUser returning undefined because the await was missing, and suggests const user = await db.findUser(id); if (!user) throw new NotFoundError(id);.


2. Turn a bug report into a failing test

When to use: QA filed a bug, but you cannot reproduce it locally. A failing test is the fastest way to make it deterministic.

Prompt:

Convert this bug report into a failing Jest test.
- Use describe/it with a clear name.
- Mock external I/O with jest.mock.
- The test must fail on the current implementation and pass after the fix.

BUG REPORT:
PASTE_REPORT

CURRENT CODE:
PASTE_CODE

Example: "Cart total shows 0 when a discount code is applied twice." The model generates a test that applies SAVE10 twice and expects total to remain 90, not 0.

Tip: Run the test before the fix — a red test is your proof of reproduction.


3. Explain a cryptic async bug (race condition)

When to use: The code works 99% of the time, then fails under load. Classic symptom of a race condition or an unawaited promise.

Prompt:

Analyze this async code for race conditions and unhandled promise rejections.
For each issue: name it, show the exact line, and give a corrected version using Promise.all, AbortController, or a mutex if needed.
Explain the fix as if to a mid-level developer.

CODE:
PASTE_CODE

Example input: a for loop with await inside that pushes to a shared array.

Expected result: The model flags the shared array mutation and rewrites it with await Promise.all(items.map(fetchItem)), noting that order is no longer guaranteed.


4. Generate unit tests with edge cases (Jest)

When to use: You wrote a pure function and want coverage fast, including boundaries you would forget.

Prompt:

Write Jest unit tests for the function below.
Cover: normal input, empty input, null/undefined, boundary values, and one property-based case.
Use TypeScript. No external libraries except Jest.
Add a short comment above each test explaining what it protects against.

FUNCTION:
PASTE_FUNCTION

Example: slugify(title: string) — the model adds tests for Cyrillic input, trailing spaces, and a 10 000-character string.


5. Find the memory leak in a Node.js service

When to use: Your container restarts every few hours with OOM. Heap snapshots show growth, but you cannot spot the retainer.

Prompt:

This Node.js service leaks memory. Here is the suspect code and a heap snapshot summary (top constructors by retained size).
1. List the top 3 likely leak sources.
2. Explain the retention path for each.
3. Give a code fix and a way to verify it with --inspect and heap snapshots.

CODE:
PASTE_CODE

HEAP SUMMARY:
PASTE_SUMMARY

Example: a Map used as a cache that is never cleared, plus an event listener added on every request. The model suggests WeakMap for object keys and emitter.off in a finally block.

Fact check: Node.js exposes process.memoryUsage() and the --inspect flag for Chrome DevTools. See the official Node.js docs on diagnostics: https://nodejs.org/en/learn/diagnostics/memory


6. Convert a flaky test into a stable one

When to use: A test passes locally but fails in CI 20% of the time. Usually it is timing, shared state, or real timers.

Prompt:

This test is flaky. Identify the non-determinism sources (real timers, Date.now, random, shared state, network).
Rewrite it to be deterministic using jest.useFakeTimers, jest.setSystemTime, and explicit mocks.
Explain each change.

TEST:
PASTE_TEST

Example: the model replaces setTimeout(..., 100) with jest.advanceTimersByTime(100) and freezes Date.now with jest.setSystemTime(new Date('2026-10-16')).


7. Generate e2e tests with Playwright

When to use: You have a critical user flow (login → checkout) and want a smoke test that runs in CI.

Prompt:

Write a Playwright e2e test in TypeScript for this flow.
- Use role-based selectors (getByRole, getByLabel) over CSS.
- Add a web-first assertion for each step.
- Include a beforeEach that logs in via API, not UI.

FLOW:
PASTE_FLOW

HTML SNIPPET:
PASTE_HTML

Example: the model produces a test that fills the checkout form and asserts await expect(page.getByRole('heading', { name: 'Order confirmed' })).toBeVisible().

Playwright's docs recommend role-based locators for resilience: https://playwright.dev/docs/locators


8. Audit TypeScript types for any leaks

When to use: Your tsconfig has strict: true, but any still sneaks in through third-party types.

Prompt:

Scan this code for places where `any` or `unknown` weakens type safety.
For each: explain the risk and propose a precise type or a type guard.
Do not use `as` casts unless unavoidable — prefer narrowing.

CODE:
PASTE_CODE

Example: a JSON response typed as any becomes interface ApiUser { id: string; email: string } plus a zod schema for runtime validation.


9. Write a regression test from a fixed bug

When to use: You just fixed a bug. Without a regression test, it will come back.

Prompt:

I fixed a bug. Here is the diff and the original bug description.
Write a regression test that would have caught it.
Name the test after the bug (e.g., 'does not double-apply discount').

DIFF:
PASTE_DIFF

BUG:
PASTE_BUG

Example: the diff adds a guard if (applied.has(code)) return total;, and the test asserts the total stays 90.


10. Generate mocks and fixtures for a module

When to use: Your test setup is 200 lines of hand-written mocks. Let the model draft them.

Prompt:

Generate Jest mocks and fixtures for this module.
- Mock only the public API used by the caller.
- Provide a factory function so tests can override fields.
- Keep fixtures realistic (use ISO dates, UUIDs).

MODULE:
PASTE_MODULE

CALLER:
PASTE_CALLER

Example: a createUserFixture(overrides) factory that returns a typed User with defaults, so tests read createUserFixture({ role: 'admin' }).


11. Profile a slow function and suggest optimizations

When to use: A function takes 800 ms and you suspect O(n²) or repeated I/O.

Prompt:

Analyze this function for performance.
1. Estimate its time complexity.
2. Point out redundant work (loops, allocations, I/O).
3. Rewrite it and state the expected improvement in Big-O terms.

FUNCTION:
PASTE_FUNCTION

INPUT SIZE:
PASTE_SIZE

Example: nested find inside map becomes a Map lookup, turning O(n²) into O(n).


12. Catch unhandled rejections and silent failures

When to use: Errors vanish. No logs, no alerts — just wrong data.

Prompt:

Find all places in this code where errors can be silently swallowed:
- empty catch blocks
- .catch(() => {})
- ignored return values of promises
- missing process.on('unhandledRejection')
For each, show the fix and a logging strategy.

CODE:
PASTE_CODE

Example: the model flags .catch(() => {}) and replaces it with .catch(err => logger.error({ err }, 'payment failed')).


13. Generate a test for a React hook with fake timers

When to use: You have a debounce or polling hook and want to test it without waiting in real time.

Prompt:

Write a test for this React hook using @testing-library/react and Jest fake timers.
- Use renderHook from @testing-library/react.
- Advance timers with act.
- Assert the final state after debounce.

HOOK:
PASTE_HOOK

Example: useDebouncedValue(value, 300) — the test advances 300 ms inside act and asserts the debounced value updates once.


14. Turn a console.log session into a structured debug plan

When to use: You have 40 console.log lines and no idea which one matters.

Prompt:

Here are my console.log statements and their output.
Reconstruct the execution flow, identify the first anomaly, and propose a minimal set of breakpoints or assertions.
Suggest a better logging approach (levels, correlation IDs).

LOGS:
PASTE_LOGS

Example: the model spots that userId becomes undefined after a JSON.parse, because the key was user_id — a naming mismatch.


Prompt Best for Typical output
1. Stack trace Undefined errors Root cause + fix
2. Bug → test Non-reproducible bugs Failing Jest test
3. Async audit Race conditions Corrected async code
4. Unit tests Pure functions Jest suite
5. Memory leak OOM in production Retention path + fix
6. Flaky test CI instability Deterministic test
7. E2E Critical flows Playwright test
8. Type audit any leaks Precise types
9. Regression Post-fix safety Regression test
10. Mocks Test setup Typed fixtures
11. Profiling Slow functions Optimized code
12. Silent errors Lost exceptions Logging strategy
13. React hooks Debounce/polling renderHook test
14. Debug plan Log chaos Breakpoint plan

The real value of these prompts is not that ChatGPT writes code for you — it is that it forces you to articulate the bug precisely. A vague question gets a vague answer; a stack trace, a diff, and a heap summary get a fix. Start with prompt #1 and #2 tomorrow: reproduce the bug as a failing test, then let the model propose the fix. You will spend less time guessing and more time shipping.

If you want to go deeper into debugging and testing workflows, asibiont.com/blog has more hands-on breakdowns — pick one, paste your code, and see the difference.

← All posts

Comments