Troubleshooting
Common failures across safe setup, safe analyse and safe sca, with the message SAFE prints,
what causes it, and what to do. Language-specific entries are marked.
Every safe analyse error exits 1; exit code 2 means the analysis succeeded and found
vulnerabilities.
License and fingerprint
| Message | Cause | Fix |
|---|---|---|
License not found. Please ensure you have a valid license set in the SAFE_LICENSE environment variable. | SAFE_LICENSE is unset | Set it — in CI, as a secret. Gleam projects never need it during the free beta |
License signature verification failed... / Failed to decode license: Invalid base64 encoding. | The license string is truncated or corrupted | Re-copy it whole; watch for line breaks added by CI variable editors |
License fingerprint does not match the current project... | The license was issued for a different project | Re-run safe setup, send the new fingerprint.json to safe@erlang-solutions.com |
Your license has expired on <date>... | Validity period ended | Contact us to renew |
Your project's Lines of Code (LOC) of N has exceeded the licensed amount... | The codebase outgrew the license | Analysis continues while the overage is small; the command starts failing 1,500 lines over, and stops analysing 2,000 over. Upgrade the license |
The Gleam free beta ended on <date>... | The free beta for Gleam analysis has ended (Gleam) | Update SAFE to the current release, or get a license and run safe setup gleam |
Configuration
| Message | Cause | Fix |
|---|---|---|
Config file not found at <path>... | No .safe/config.json where SAFE looked | Run safe setup, or pass --config-path. For a Gleam project run without a config, it also means no built project in the current directory — cd to the root holding gleam.toml |
Failed to parse config: Invalid JSON format. | Malformed config.json | Validate the JSON |
--config-path and --config-json cannot be used together. | Both flags given | Pass one |
The --project-root argument is required when using --config-json. | Inline config without a root | Add --project-root |
Could not find an .app file for app "<app>"... | The app name in the config does not match the build output, or the project is not compiled | Compile, then check apps and paths in the config |
No source files were found to analyse. SAFE could not generate a project fingerprint. | apps/paths point somewhere with no compiled code | Compile (mix compile, rebar3 compile, gleam build), then check the paths the message lists |
Compilation and analysis
| Message | Cause | Fix |
|---|---|---|
One or more beam files are missing abstract code... | BEAMs compiled without debug_info — often a vendored or pre-built dependency | Recompile with debug_info, or re-run with --no-abstract-code-check to skip those files |
The <beam> file for app "<app>" was not compiled with debug_info... | Same, caught at setup time | As above |
An unexpected error occurred while analysing your project... | Unhandled failure | Re-run after safe analyse clean; if it persists, send us the command and output |
| A finding you already fixed is still reported | SAFE analysed stale build output | Rebuild before analysing. If it persists, safe analyse clean and re-run |
| An ignore comment has no effect | It names a function SAFE did not report, or sits on the wrong line | There is no warning when a comment fails to match — see Ignore false positives |
| Results look wrong after a big restructure | Stale analysis database | safe analyse clean, then analyse again |
Incremental analysis
SAFE keeps its state in ~/.safe. Caching that directory between CI runs speeds up later
analyses; safe analyse clean wipes it when you need a cold start.
Supply Chain Analysis
| Message | Cause | Fix |
|---|---|---|
Could not find mix.lock, rebar.lock, or manifest.toml file... | No lock file in the current directory | cd to the project root, or pass --lock-file |
Found more than one of mix.lock, rebar.lock, and manifest.toml... | Several lock files side by side | Name the one to scan with --lock-file |
Failed to fetch the advisory database... | No network access | safe sca needs a connection; allow it through the proxy or firewall |
Invalid .safe/sca_ignore.json file... | Malformed ignore file | See Suppressing SCA findings for the expected structure |
| Dependencies reported as warnings, not scanned | Non-Hex sources — :git, :path, and Gleam local/git entries | Expected: they have no Hex identity to match against advisories. Suppress accepted ones with ignored_non_hex_packages |
Gleam-specific
See Gleam projects for the workflow these refer to.
| Symptom | Cause | Fix |
|---|---|---|
... no compiled output was found at build/dev/erlang | Not built for the Erlang target | Run gleam build. The JavaScript target produces nothing SAFE can read |
No gleam.toml found at <root>... | safe setup gleam run outside a project root | cd to the root, or pass --root |
Failed to read gleam.toml: <reason>... | Invalid TOML, or no name field | Fix gleam.toml |
License not found... on a Gleam project | SAFE could not confirm a Gleam project, so the ordinary licensed path applies | Check gleam.toml sits at the project root and that gleam build has compiled every app the config names. A build tree mixing Gleam with Erlang or Elixir apps is not covered by the beta |
No report file after safe analyse | Run without a config, SAFE prints to the console only | Generate a config with safe setup gleam; it stays free during the beta |
| The reported line is not where the call is | Findings anchor to the function declaration, not the call | Read the whole snippet — see Gleam projects |
A finding points into test/ or dev/ | The module was in additional_includes, or SAFE could not match the compiled modules to the package's sources and analysed all of them rather than under-report (it logs a warning) | Remove it from the config, or check the sources sit beside the build output |
| Findings you expected are missing | Only src/ is analysed | Add the module's .beam to additional_includes |
An // safe-ignore comment does nothing | It must name the Erlang function (binary_to_atom/1, not atom.create/1) and sit immediately above pub fn | See Ignore false positives |
Still stuck?
Contact safe@erlang-solutions.com with the command you ran and
the output you got. Include .safe/config.json if you have one — and if the run produced a log,
redact it first.