tadka: Structured error diagnostics & source-span reporting like Rust's miette

[ development, error-handling, library, mpl ] [ Propose Tags ] [ Report a vulnerability ]

Tadka is a Haskell library for structured error diagnostics and source-span reporting. It turns ordinary error values into diagnostic reports with source locations, labeled spans, error codes, severity, help text, documentation URLs, related diagnostics, and underlying causes. It provides graphical terminal, accessible prose, and JSON renderers, with support for diagnostics spanning multiple source files. Tadka also provides integrations for GHC SrcSpan, Megaparsec, and Attoparsec, plus Template Haskell derivation support for reducing diagnostic boilerplate. It is inspired by Rust's miette but is designed around Haskell's types and conventions.


[Skip to Readme]

Flags

Manual Flags

NameDescriptionDefault
werror

Treat warnings as errors (enable in dev/CI, off for releases).

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 2.0.0.0
Change log CHANGELOG.md
Dependencies aeson (>=2.1 && <2.4), ansi-terminal (>=1.0 && <1.2), array (>=0.5 && <0.6), attoparsec (>=0.14 && <0.15), base (>=4.18 && <4.23), bytestring (>=0.11 && <0.13), containers (>=0.6 && <0.9), ghc (>=9.6 && <9.15), megaparsec (>=9.0 && <9.9), network-uri (>=2.6 && <2.7), prettyprinter (>=1.7 && <1.8), prettyprinter-ansi-terminal (>=1.1 && <1.2), tadka, template-haskell (>=2.20 && <2.25), text (>=2.0 && <2.3) [details]
Tested with ghc ==9.6.7, ghc ==9.8.4, ghc ==9.10.3, ghc ==9.12.4, ghc ==9.14.1
License MPL-2.0
Copyright (c) 2026 Bombay-Boyz
Author Sabrinathan Nair
Maintainer 259497327+Bombay-Boyz@users.noreply.github.com
Uploaded by bombayboyz at 2026-09-13T18:31:14Z
Category Development, Error Handling
Home page https://github.com/Bombay-Boyz/tadka
Bug tracker https://github.com/Bombay-Boyz/tadka/issues
Source repo head: git clone https://github.com/Bombay-Boyz/tadka.git
Distributions
Downloads 0 total (0 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2026-09-13 [all 1 reports]

Readme for tadka-2.0.0.0

[back to package description]

Tadka

Tadka is a Haskell library for structured error diagnostics and source-span reporting.

It turns ordinary error values into useful diagnostic reports with source locations, labeled spans, error codes, help text, related diagnostics, and underlying causes.

The same diagnostic can be rendered as graphical terminal output, accessible prose, or JSON.

tadka is useful for compilers, parsers, command-line tools, static analyzers, DSLs, and other developer tooling.

It is inspired by Rust's miette, but is designed around Haskell's types and conventions.

A snapshot of the error produced by tadka is as under:

Tadka graphical diagnostic

Why tadka?

Tadka adds a reporting layer to your existing error types. It does not replace your application's error-propagation mechanism.

You can keep using:

Either MyError a

or:

ExceptT MyError IO a

or another error-handling design. Add a Diagnostic instance to describe how the error should be presented.

The main features are:

  • Source-aware diagnostics with labeled spans.
  • Graphical, narratable, and JSON output.
  • Primary and secondary labels, including collections of labels.
  • Diagnostics spanning multiple source files.
  • Error codes, severity, help text, and documentation URLs.
  • Related diagnostics and underlying cause chains.
  • Bounded rendering and cycle protection for diagnostic chains.
  • Unicode-aware source positioning, including tabs, combining characters, East Asian width, and emoji.
  • Explicit handling of stale source spans when source text has changed.
  • Adapters for GHC SrcSpan, Megaparsec, and Attoparsec.

What it looks like

A graphical diagnostic can look along these lines:

error[E1001]: unexpected token

 --> example.td:4:9
  |
4 | let x = foo(
  |         ^^^ expected an expression
  |
  = help: check the expression following `foo`

The same diagnostic can be rendered as accessible prose or as JSON, depending on the selected target.

Installation

Add tadka to your package's dependencies:

build-depends:
    tadka

Then import the public API:

import Tadka

tadka is designed to work with ordinary Cabal projects and existing Either, ExceptT, or custom error types.

Five-minute example

Define an ordinary error type:

data MyError
  = UnexpectedToken Span
  | MissingName Span
  deriving stock (Show)

Give it a diagnostic description:

instance Diagnostic MyError where
  message = \case
    UnexpectedToken _ -> "unexpected token"
    MissingName _     -> "missing name"

  context = \case
    UnexpectedToken span ->
      mkContext source
        (Labeled span Primary (Just "expected an expression") :| [])

    MissingName span ->
      mkContext source
        (Labeled span Primary (Just "a name is required here") :| [])

  code = const (Just (mkDiagnosticCode "E1001"))

Then report it:

reportDiagnostic defaultConfig err

The reporting layer remains separate from the way your application creates, returns, or handles MyError.

Deriving diagnostics

For error types where the diagnostic information follows a regular structure, tadka provides Template Haskell support.

For example:

data ParseError = ParseError
  { parseMessage :: Text
  , parseSpan    :: Span
  }
  deriving stock (Show)

$(deriveDiagnostic defaultSpec
    { specMessage     = [| \e -> pretty (parseMessage e) |]
    , specSourceField = Just 'parseSpan
    })

The derivation API can also describe error codes, help text, URLs, primary and secondary labels, related diagnostics, causes, and diagnostic identity.

Source spans

tadka keeps source text and source locations explicit.

A Span identifies a range in a named source. It can be resolved against the source text to obtain line and column information:

resolved <- resolveSpan source span

The implementation accounts for details that can make source positioning non-trivial, including:

  • tabs
  • Unicode characters
  • combining characters
  • East Asian character width
  • emoji
  • large source offsets

When source text has changed and a span can no longer be trusted, tadka represents that condition explicitly rather than silently presenting a misleading location.

Labeled source context

A diagnostic can contain primary and secondary labels:

mkContext source
  (Labeled span1 Primary (Just "the problem is here")
    :| [Labeled span2 Secondary (Just "this is also relevant")])

Multiple source files are supported as well.

tadka can also degrade stale spans when source text no longer matches the coordinates stored by an error value.

Rendering

Tadka currently provides three output targets:

  • TGraphical — terminal-oriented diagnostic output.
  • TNarratable — accessible prose-oriented output.
  • TJson — machine-readable JSON output.

A Config controls reporting behavior such as color, Unicode, hyperlinks, context lines, tab width, related-diagnostic depth, label palettes, and the selected target.

For example:

let config =
      withTarget TGraphical
      $ withColorMode ColorAuto
      $ defaultConfig

reportDiagnostic config err

The renderer selection and lower-level rendering APIs are also available when applications need more control.

Existing error types

Tadka does not require a new application-wide error architecture.

If an application already has error types, they can remain ordinary Haskell values. A Diagnostic instance describes how each error should be presented to a human or another tool.

This separation is useful when the same error value needs to be:

  • returned through Either
  • propagated through ExceptT
  • logged
  • displayed in a terminal
  • returned as JSON
  • embedded in another diagnostic

Diagnostics can contain related diagnostics and an underlying cause chain.

This lets an application represent structures such as:

top-level error
    |
    +-- related diagnostic
    |
    +-- underlying cause
            |
            +-- underlying cause

Tadka bounds traversal depth and supports diagnostic identity so that recursive or cyclic structures cannot cause unbounded rendering.

Parser and compiler integration

Tadka includes integration packages for common Haskell tooling:

tadka:interop-ghc
tadka:interop-megaparsec
tadka:interop-attoparsec

These adapters allow existing parser and compiler source locations to be translated into Tadka source-span information without requiring the application to redesign its diagnostics.

JSON output

JSON output is intended for applications that need to pass diagnostics to other programs, scripts, editor tooling, or services.

The JSON representation should be treated as an output format of the corresponding Tadka release. If another program depends on its exact shape, pinning the tadka version is the safest approach.

Accessibility

The narratable renderer provides a prose-oriented representation of the same structured diagnostic.

This is useful when graphical terminal formatting, Unicode drawing characters, or visual source annotations are not appropriate.

Public API boundary

The primary application-facing API is:

import Tadka

The package also exposes internal modules for implementation-level use, but they are not intended to provide the same compatibility guarantees as the public API.

Applications should prefer the public Tadka module unless they have a specific reason to use an internal module.

Testing and engineering

Tadka is tested across multiple supported GHC versions and includes:

  • unit and property tests
  • renderer tests
  • golden tests
  • parser/compiler interop tests
  • generated-code checks
  • compile-failure checks
  • adversarial source-position cases
  • Unicode and tab-positioning cases
  • stale-source handling
  • multi-source diagnostics
  • related/cause-chain protection

The project is developed with warnings enabled and maintains explicit dependency bounds.

Current scope

Tadka focuses on structured diagnostic representation and rendering.

It intentionally does not attempt to be all of the following at once:

  • an application-wide error-handling framework
  • an LSP implementation
  • an editor integration layer
  • a syntax-highlighting engine
  • a general-purpose logging framework
  • a replacement for parser-specific error types

Those concerns can be built around the diagnostic representation when an application needs them.

License

Tadka is released under the Mozilla Public License 2.0 (MPL-2.0).

See LICENSE for the complete license text.

Acknowledgement

The design is inspired in part by Rust's miette, particularly its approach to structured diagnostics, source snippets, labels, and human-friendly reporting.

Tadka is an independent Haskell implementation designed around Haskell's type system, libraries, and conventions.