Open-source project
aviatesk/JET.jl avatar
aviatesk/JET.jl

JET.jl: finding type instabilities and runtime errors in Julia

A code analyzer for Julia. No need for additional type annotations.

884 stars44 forksJuliaMIT

At a glance

What is it?
JET.jl is a static analyzer for Julia that reuses the language's own type inference to report possible runtime errors and type instabilities, with no extra type annotations required from you. It suits Julia developers whose code is slow or crashes for reasons the compiler cannot warn about.
Who is it for?
JET.jl is a good fit for a Julia developer who has hit a performance wall caused by type instability or a MethodError that only appears on some input, and who wants a tool that reads the code the compiler already reads rather than a separate annotation scheme.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Julia, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It reads the compiler's own inference rather than a second type system

The premise is stated in one line and it is what separates JET from a linter with type rules bolted on. JET employs Julia's type inference system to detect potential bugs and type instabilities, and the project description says it needs no additional type annotations. That is the practical difference from tools that ask you to declare types so they can check them, because in a Julia codebase that has deliberately stayed dynamically typed, asking for annotations is asking for a change of style. Using the language's own inference means the analyzer sees the same types the compiler will specialise on at run time, including the ones inferred through generics and multiple dispatch, and the report it produces is the runtime dispatch the compiler would actually pay for. The repository topics list error detection, Julia, performance engineering and static analysis, which is the same pair of jobs the documentation describes, since the two macros in the readme are for type instabilities and for type errors separately.

The compatibility rules are stricter than the install rules

This is the part of the documentation that deserves the most attention, because it is unusual and it will bite. JET distinguishes installation compatibility from functional compatibility. The latest series keeps its Julia upper compatibility bound open, which allows packages with JET as a test dependency to instantiate on Julia pre-releases and nightly builds, but full JET functionality is loaded only on explicitly supported Julia versions, and on unsupported future versions JET loads empty stubs and its analysis APIs throw an explanatory error. The current note says the v0.12 release series supports full functionality on Julia v1.12 and v1.13 only, and that the version working with Julia v1.11 is the v0.9 series, where bug fixes and new features from later series are not necessarily available. The version numbering reflects that, since minor versions are bumped for ordinary semantic versioning reasons and may also mark a new Julia compatibility generation, while patch releases normally stay inside the same generation. The JET_AVAILABLE constant exists so a test suite can ask the question at run time and skip its JET-specific tests when the answer is no:

julia
using JET

if JET.JET_AVAILABLE
    include("jet_tests.jl")
end

There is also a development mode preference, JET_DEV_MODE, that forces JET to try loading full functionality on an unsupported Julia version.

Why the results move when Julia moves

The warning section explains a limitation that is really a property of the approach. Because of JET's tight integration with the Julia compiler, the results presented by JET can vary significantly depending on the version of Julia you are using, and the implementation of the Base module and the standard libraries bundled with Julia can also affect the results. On top of that, Julia's compiler plugin system is unstable and changes frequently, which is why each JET release supports full functionality on only a limited set of Julia versions. This is the honest cost of a tool that lives inside the compiler rather than beside it, and it is a very different failure mode from a linter whose output only changes when your code changes. The practical consequence for a team is that a JET report is only meaningful relative to a Julia version, so a CI matrix spanning several Julia versions will produce different findings on each, and a finding that appears on one and not another is usually about the Julia version rather than about your code.

Two macros for two different failure modes

The readme documents the two entry points and the relationship between them. Type instabilities are detected in function calls using the report_opt macro, which works similarly to the code_warntype macro in the standard library. Potential bugs are detected with report_call, and the documentation is specific that this covers calls that may throw at run time, such as MethodErrors. The example for report_call folds a character vector and the report shows a stack of the internal reduce implementation with the point at which the dispatch goes wrong. There is an important caveat about what the analyzer can see. Because JET relies on Julia's type inference, it cannot see through unresolved dynamic dispatch, so callees reached only through such calls are not analyzed and problems inside them go unreported. That produces a practical ordering advice in the documentation, since fixing the instabilities reported by report_opt first lets report_call cover more of the code, while noting that report_call is often less noisy than report_opt, so starting with report_call alone is perfectly reasonable. The report format is a stack trace of the call chain, which is what makes the output actionable rather than a bare list of warnings.

Installing it, and the dependency trap that comes with it

JET is a standard Julia package, installed with the built-in package manager:

julia
julia> using Pkg; Pkg.add("JET")

The documentation then adds two warnings that are worth internalising. The package manager installs a JET version allowed by the registry metadata and your environment's constraints, which does not necessarily mean full functionality is supported on your Julia version, so you should check JET.JET_AVAILABLE after loading. And existing dependencies may prevent a working JET version from being installed. The specific case named is JuliaInterpreter, which is also a dependency of the widely used Revise package, so an incompatible JuliaInterpreter version can block a working JET install. The recommended workaround in that situation is a temporary environment, created with Pkg.activate with the temp flag set, and using JET there. The registry side is handled too, with older JET releases capped in the General registry at the last Julia minor they support when a new generation is released, which stops package resolution and lower-bound testing from selecting an old incompatible version.

What the repository holds, and where the project is going

The source layout is a Julia package with a src directory, an ext directory for extensions, a test directory, a docs directory, an examples directory and a benchmark directory, plus the project manifest, a language server configuration file, a changelog, a licence and an agent instruction directory. The examples directory is more interesting than a list of scripts usually is, because it has its own manifest and project file, and it includes a dispatch analysis example and one for finding an unstable API, which are the two problems that are hard to find by hand. There is also a demo file and a diff that fixes it, which suggests the demo is kept honest. The release history shows a steady cadence on the 0.12 series, with v0.12.3 on 2026-10-03, v0.12.2 on 2026-09-24 and v0.12.1 on 2026-08-08, and the last push was on 2026-10-22, so the project is actively maintained even though it has not reached a 1.0 release. The licence is MIT. The documentation site has a development version of the manual, and the readme points to it for more commands, options and explanations than the quickstart covers.

Editorial conclusion

JET.jl is a good fit for a Julia developer who has hit a performance wall caused by type instability or a MethodError that only appears on some input, and who wants a tool that reads the code the compiler already reads rather than a separate annotation scheme. It is the wrong tool if you need analysis on a Julia version outside the supported set, because the package loads empty stubs and the analysis APIs throw an explanatory error, and it is the wrong tool if you need the results to be stable across Julia upgrades, because the documentation warns that the results can vary significantly with the Julia version. It is also the wrong tool for a codebase with heavy dynamic dispatch, since the analyzer cannot see through unresolved dispatch and the callees behind it go unreported. Before adopting it, check the compatibility notes and confirm JET.JET_AVAILABLE is true in your environment after loading. The project is MIT licensed, the last push was on 2026-10-22, and the current release is v0.12.3 from 2026-10-03.

Frequently asked questions

What does JET.jl detect?

It employs Julia's type inference to detect potential bugs and type instabilities. The report_opt macro finds type instabilities in function calls, working similarly to the code_warntype macro, and report_call finds potential bugs, meaning calls that may throw at run time such as MethodErrors.

Which Julia versions does JET.jl support fully?

The latest release series, v0.12, supports full JET functionality on Julia v1.12 and v1.13 only. The v0.9 series is the one that works with Julia v1.11, though bug fixes and features from later series are not necessarily available there. On an unsupported version JET still installs but loads empty stubs and its analysis APIs throw an explanatory error.

How do I install JET.jl?

It is a standard Julia package, so use the built-in package manager with using Pkg and Pkg.add for the package name. Check JET.JET_AVAILABLE after loading, because installing does not guarantee full functionality. If a dependency blocks a working version, the documentation recommends a temporary environment created with Pkg.activate and the temp flag set.

What are the limitations of JET.jl analysis?

Because it relies on Julia's type inference, JET cannot see through unresolved dynamic dispatch, so callees reached only through such calls are not analyzed and problems inside them go unreported. The documentation also warns that results can vary significantly with the Julia version, since the Base module implementation and the compiler plugin system both change.

Why do JET.jl results differ between Julia versions?

Because of the tight integration with the Julia compiler, so the results can vary significantly depending on the Julia version, and the implementation of Base and the standard libraries can affect them too. Julia's compiler plugin system is unstable and changes frequently, which is why each JET release supports full functionality on only a limited set of Julia versions.

Official sources

  1. aviatesk/JET.jl on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/aviatesk-jet-jl.svg)](https://hysenlabs.com/projects/aviatesk-jet-jl)

Was this useful?