How to Use Problem Matchers with VS Code Tasks

Attach problem matchers to VS Code tasks so compiler and linter errors appear in the Problems panel as clickable entries. Use built-in matchers or write your own.

6 min read

A VS Code problem matcher scans task output and turns matching errors or warnings into entries in the Problems panel. Open that panel with Ctrl+Shift+M on Windows or Linux, or Shift+Cmd+M on macOS, then select an entry to open its file and location.

Without a matcher, the task still runs, but you must inspect its terminal output yourself.

Use a built-in problem matcher

VS Code ships with matchers for common tools. If you need a task first, start with the tasks.json guide. Reference a built-in matcher by name with a dollar-sign prefix:

Matcher nameTool it parses
$tscTypeScript compiler
$tsc-watchTypeScript in watch mode
$eslint-compactESLint compact format
$eslint-stylishESLint stylish format
$jshintJSHint
$jshint-stylishJSHint stylish format
$goGo compiler
$mscompileC# and VB compiler
$lesscLess compiler
$node-sassNode Sass compiler

To use one, add it to the problemMatcher array in your task. You can attach a single matcher or multiple matchers:

jsonjson
{
  "label": "Full check",
  "type": "shell",
  "command": "npm run check",
  "problemMatcher": ["$tsc", "$eslint-stylish"]
}

This example assumes the project's check script emits TypeScript and ESLint stylish output. When it runs, matching errors appear in the Problems panel with their file path, line number, and message.

The current built-in list and behavior are documented in the official VS Code Tasks guide.

Modify a built-in matcher

Sometimes a built-in matcher is close to what you need but not exact. You can modify it instead of writing a new one from scratch.

For example, the $tsc-watch matcher applies to closed documents by default. To report problems for all documents, reference it with base and set applyTo to allDocuments. You can also override background, fileLocation, owner, pattern, severity, and source this way.

Add this matcher object to the task that runs TypeScript in watch mode:

jsonjson
{
  "base": "$tsc-watch",
  "applyTo": "allDocuments"
}

Save tasks.json, run the watch task, and introduce a temporary TypeScript error in a closed file. If the override works, that file appears in Problems. Undo the test error afterward.

Write a custom problem matcher

If your tool has no built-in matcher, write your own. A custom matcher uses a regular expression to parse the tool's output format.

First, capture a real error line from your tool. For example, the GCC compiler produces this output when it finds a problem:

texttext
helloWorld.c:5:3: warning: implicit declaration of function 'prinft'

The error line contains the file name, line number, column, severity, and message. You need a regular expression that captures each of these parts into separate groups. Here is a complete task with a custom matcher that parses the GCC format above:

jsonjson
{
  "label": "Build with GCC",
  "type": "shell",
  "command": "gcc -Wall helloWorld.c -o helloWorld",
  "problemMatcher": {
    "owner": "cpp", "source": "gcc",
    "fileLocation": ["relative", "${workspaceFolder}"],
    "pattern": {
      "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
      "file": 1, "line": 2, "column": 3,
      "severity": 4, "message": 5
    }
  }
}

The parts explained:

PropertyWhat it does
ownerIdentifier VS Code uses to group related problems.
fileLocationHow VS Code resolves relative or absolute paths. The example resolves paths from the workspace root.
regexpThe regular expression. Each pair of parentheses creates a capture group.
fileWhich capture group contains the file path (1-based index).
lineWhich group contains the line number.
columnWhich group contains the column number. Optional.
severityWhich group contains "warning" or "error". Optional; defaults to error if omitted.
messageWhich group contains the error message.

The file, line, and message properties are required. The rest are optional.

Use a regex tester such as RegEx101 with the ECMAScript flavor to test a copied output line before adding the pattern to tasks.json. Then run the task and confirm the expected file and location appear in Problems.

Handle multi-line output

Some tools spread an error across multiple lines. ESLint in stylish mode outputs the file name on one line, then each problem on the next line.

For multi-line output, use an array of patterns:

jsonjson
{
  "pattern": [
    { "regexp": "^([^\\s].*)$", "file": 1 },
    {
      "regexp": "^\\s+(\\d+):(\\d+)\\s+(error|warning|info)\\s+(.*)\\s\\s+(.*)$",
      "line": 1, "column": 2, "severity": 3,
      "message": 4, "code": 5, "loop": true
    }
  ]
}

The first pattern captures the file name. The second pattern, with loop: true, matches every subsequent problem line under that file. Each line becomes a separate entry in the Problems panel.

Use problem matchers with watch tasks

Watch tasks run continuously and produce output in bursts. VS Code needs to know when a burst of errors starts and ends.

The built-in $tsc-watch matcher already tracks TypeScript watch output. A complete watch task can use it directly:

jsonjson
{
  "label": "TypeScript watch",
  "type": "shell",
  "command": "tsc --watch",
  "isBackground": true,
  "problemMatcher": "$tsc-watch"
}

For another tool, define a custom matcher's background object with patterns copied from its real output. activeOnStart marks the watcher active immediately, while beginsPattern detects a new processing cycle.

endsPattern detects the ready or inactive state. The patterns matter when a sequential dependency or preLaunchTask must wait until the watcher is ready.

Run the task, confirm its ready line appears, and verify that later errors update Problems.

Troubleshooting

The Problems panel stays empty after a task runs

Check that your problemMatcher name is correct. Built-in matchers use a dollar-sign prefix: $tsc, not tsc.

Also check that the task produced output in the format the matcher expects. Run the command in a terminal first and compare its output with the matcher format.

Problems appear but clicking them does not open the right file

The fileLocation is wrong. Use absolute for absolute paths, relative for paths based on the task's working directory, or autoDetect when output can contain either form.

A tested regex does not match task output

VS Code uses JavaScript regular expressions. Make sure you are testing with the ECMAScript flavor. Also check that backslashes are properly escaped: in JSON, a single backslash in the regex becomes a double backslash (\\d for a digit).

Once your problem matchers are working, learn how to create dependent, background, and compound tasks to chain multiple tools together.

Rune AI

Rune AI

Key Insights

  • VS Code ships with built-in problem matchers for TypeScript ($tsc), ESLint ($eslint-stylish, $eslint-compact), JSHint, Go, C#, Less, and Node Sass.
  • Add a problemMatcher to a task to parse matching output into clickable entries in the Problems panel.
  • Use multiple matchers when one task produces more than one supported output format.
  • For tools without a built-in matcher, write a custom regexp that captures the file, location, and message.
  • Use a background-aware matcher when VS Code must track a watch task's processing and ready states.
RunePowered by Rune AI

Frequently Asked Questions

What happens if I do not add a problem matcher?

The task still runs and its output still appears in the terminal, but matching errors are not added to the Problems panel. You must inspect the terminal output yourself.

Can I use multiple problem matchers on one task?

Yes. The problemMatcher property accepts an array. Use ["$tsc", "$eslint-stylish"] when one task produces output in both supported formats.

Do problem matchers work with background or watch tasks?

Yes. Mark the task with isBackground: true. Use a background-aware matcher, such as $tsc-watch, when VS Code must track active and inactive periods or know when a dependency or preLaunchTask is ready.

How do I test a custom problem matcher regex?

Copy real output from the tool and test the expression with the ECMAScript flavor. Confirm that each configured capture group maps to the intended file, location, severity, and message.

Conclusion

Problem matchers turn raw terminal output into structured errors you can click to jump to. Start with the built-in matchers: $tsc for TypeScript, $eslint-stylish for ESLint, $go for Go. If your tool has no built-in matcher, write a custom one with a regular expression. Once errors appear in the Problems panel, you can fix them without scrolling through the terminal.