DEV Community

Taylor Wang
Taylor Wang

Posted on

Stop Asking Bug Reporters for More Details. Generate the Reproducer Yourself.

Most bug reports cost more time in clarification than in fixing.

A maintainer gets an issue like this:

parseRelative('tomorrow at 2:30 pm') returns Invalid Date on Node 18, but it worked on Node 16. Can you fix it?

No code, no package version, no test case. The natural response is to ask for more information, wait two days, get a partial answer, ask again, and only then start looking at the actual bug. For projects with a steady stream of issues, that loop eats more hours than the patch itself.

A lower-friction alternative is to turn the report into a runnable reproducer yourself, before replying at all. A free model can draft that reproducer from the issue text, and a free server can run it against multiple Node versions away from your own machine. This article shows a concrete workflow for that, including a reproducible example and a decision table for when it is worth doing.

The real cost is in the back-and-forth

When a report is vague, the maintainer usually becomes a detective asking for the same five things: environment, package version, input, expected output, and a minimal example. Each round trip can take days. In that time, the original reporter may lose interest, and the maintainer loses context.

The alternative is to treat the issue as a seed for a reproducer rather than a demand for a complete problem statement. You read the report, guess the missing parts, generate a small script, and run it. If the script reproduces the reported error, you now have something concrete to fix. If it does not, you can reply with a reusable example and ask the reporter to adjust one line instead of asking them to build a full test case.

Reproducible example: date parsing across Node versions

Consider a tiny library with this function, which the maintainer knows is part of the public API:

// parseRelative.js
export function parseRelative(input, now = new Date()) {
  const lower = input.toLowerCase();

  if (lower.startsWith('tomorrow')) {
    const base = new Date(now);
    base.setDate(base.getDate() + 1);

    const timeMatch = lower.match(/(\d{1,2}):(\d{2})\s*(am|pm)?/);
    if (timeMatch) {
      const hours = Number(timeMatch[1]);
      const minutes = Number(timeMatch[2]);
      const meridian = timeMatch[3];
      let hour = hours;
      if (meridian === 'pm' && hour !== 12) hour += 12;
      if (meridian === 'am' && hour === 12) hour = 0;
      base.setHours(hour, minutes, 0, 0);
    }

    return base;
  }

  return new Date(NaN);
}
Enter fullscreen mode Exit fullscreen mode

The issue says the call parseRelative('tomorrow at 2:30 pm') fails on Node 18 but worked on Node 16. The likely culprit is a change in how Node handles a Date object passed as the default argument when the function is invoked without a second argument: the default value is evaluated once at call time, but new Date() is captured at a different point in some older code paths. A quick manual test on Node 18 may or may not reproduce the report depending on the local time and environment.

Instead of guessing on your laptop, you can generate an isolated reproducer script that pins the input and prints the result in a way that is easy to compare across versions.

// reproducer.mjs
import { parseRelative } from './parseRelative.js';

const fixedNow = new Date('2026-08-14T10:00:00Z');
const result = parseRelative('tomorrow at 2:30 pm', fixedNow);

if (Number.isNaN(result.getTime())) {
  console.error('Reproduced: returned Invalid Date');
  process.exit(1);
}

console.log(result.toISOString());
console.log('Expected: 2026-08-15T14:30:00.000Z');

process.exit(0);
Enter fullscreen mode Exit fullscreen mode

The important detail is the second argument to parseRelative. In the original report, the user wrote the call without passing a now, so the function uses its default new Date(). That is exactly the version-dependent part, because the default value is constructed at call time but may interact with the engine's handling of Date and timezone in subtle ways that changed between Node 16 and Node 18.

Step 1: Extract the missing pieces from the issue text

You do not need a full issue template to use this workflow. You need only a prompt that asks for a minimal script, not a patch. Keep the prompt focused on what is visible in the report:

Given this GitHub issue text, generate a minimal Node.js reproducer script that prints the result and exits nonzero if the error occurs.

Issue text:
<message body>

Function signature and file path:
export function parseRelative(input: string, now?: Date): Date

Use only Node built-in modules and one imported function. Export nothing. Print the result as ISO 8601.
Enter fullscreen mode Exit fullscreen mode

Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode's free model access can produce this first draft from the issue body, and its free server option gives you a clean place to run the script before you install anything locally. The same approach works with any model endpoint or a disposable container; the value comes from generating the reproducer instead of asking the reporter to do it.

Keep the prompt limited to the issue text and the known function signature. Do not paste tokens, database URLs, or a private repository into a free endpoint, and do not run the generated script against a production system.

Step 2: Run the reproducer in a clean environment

On your laptop, the bug may or may not appear because your Node version, timezone, and dependencies differ from the reporter's. A free server lets you run the same script against multiple Node images without polluting your local setup.

A minimal runner file can look like this:

# .github/workflows/reproducer.yml
name: Reproducer check
on:
  workflow_dispatch:
jobs:
  node-matrix:
    strategy:
      matrix:
        node: [16, 18, 20]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: node reproducer.mjs
Enter fullscreen mode Exit fullscreen mode

If you prefer not to use GitHub Actions, the same script can run on MonkeyCode's free server as a one-off task. The benefit is a clean base image with a controlled Node version and no inherited shell history, which removes the \u201cworks on my machine\u201d factor from the conversation.

Step 3: Reply with the reproducer, not a request for more info

Once your script reproduces the issue on Node 18 and passes on Node 16, your reply to the reporter becomes much shorter:

I generated a minimal reproducer at reproducer.mjs. It prints the expected ISO date on Node 16 and exits with \u201cReproduced\u201d on Node 18. Can you confirm this matches your environment? If yes, I will start a fix from this baseline.

This moves the conversation from \u201ccan you provide more details?\u201d to \u201chere is a concrete artifact, please confirm.\u201d The reporter only needs to run one command. If they do not respond, you still have a local failing script that is a stronger starting point than a vague issue title.

When to generate a reproducer yourself

Issue pattern Generate a reproducer? Why
Environment-specific behavior Yes Version and OS drift are hard for reporters to diagnose
Public API with missing context Yes The maintainer can infer from known signatures
Report includes code and a failing test No The reporter already did the work
Security-sensitive input or logs No Do not pass sensitive material to a free model
Report is about a private internal service No The reproducer cannot run on a free runner

The workflow is not a replacement for good issue templates. It is a fallback for the many reports that do not follow them, and a way to turn a ambiguous message into a concrete artifact without waiting for a reply.

Who should not use this approach

If you have very few issues, the cost of prompting and running may exceed the cost of asking for details. If the code involves proprietary logic or sensitive data, keep the reproducer on a local machine or an internal CI runner. If the issue already includes a failing test with clear expectations, your time is better spent reading the test than generating a new one.

Tools change the latency, not the principle. The useful habit is to convert a report into something executable before you start guessing. Whether you use a free model, a local LLM, or your own brain, the first reply to a vague bug report should ideally be a reproducible artifact, not another question.

Top comments (0)