Skip to main content
Version: Latest

Troubleshooting

Quick Diagnosis

SymptomLikely CauseFix
Everything marked "new"Missing baselineMount /main, set CODEWARD_MODE=diff
No PR commentMissing env varsSet CODEWARD_GITHUB_TOKEN, PR_NUMBER, OWNER, REPOSITORY
Empty reportWrong change filterInclude new in changes
Template error with JSONtemplate set for JSONRemove template field
Invalid field errorWrong field for policy typeCheck Policies
Relationship filter ignoredDependency tree disabledSet global.dependency_tree: true
Rule not workingMisunderstood rule logicRules find problems, not enforce requirements

Rule Logic

Common confusion: Rules define what to search for, not requirements.

What You WantCorrect Rule
Find CRITICAL vulns{ type: eq, value: CRITICAL }
Find large PRs (>30 files){ type: gt, value: "30" }
Find missing test script{ type: not_exists, key: scripts.test }
Find WIP PRs{ type: contains, value: WIP }
Find Dockerfiles without USER{ type: not_contains, value: USER }

Think: ✅ "Find what I want to block" — not ❌ "Define requirements".

License Rules Match Nothing

Almost always the Category value. It is matched exactly and is lowercase, and there is no Copyleft category — a rule using it validates cleanly and then matches nothing, silently.

SymptomCauseFix
Category eq Copyleft finds nothingNo such categoryCategory in "restricted,forbidden", or reciprocal for MPL/EPL/CDDL
Category eq Restricted finds nothingValues are lowercaserestricted
A license you expect to be flagged reports unknownNeither the built-in table nor Intel recognises itCheck LicenseSource in your output to see where the license came from
LGPL not matched by a reciprocal ruleLGPL is restricted by defaultMatch restricted, or enable CODEWARD_INTEL_CLASSIFICATION — see License categories

The seven valid values are forbidden, restricted, reciprocal, notice, permissive, unencumbered and unknown.

Docker Volumes

MountPurposeRequired
/mainMain/base branchYes
/branchFeature branchOnly for diff mode
/resultsOutput filesIf using file: destinations
/tmp/.cacheIntel snapshot segments + license cacheStrongly recommended

Validation Errors

ErrorFix
invalid formatUse markdown, html, json, or sarif
invalid destinationStart with git:, github:, log:, file:, or url:
template must be emptyRemove template for JSON outputs
invalid fieldUse only allowed fields for the policy type
webhook only valid on url: destinationsMove webhook config to a url: output

Performance Tips

  1. Persistent cache — mount /tmp/.cache so snapshot segments survive between runs. This is the single biggest win: a cold cache re-downloads ~87 MB for an npm project every time, and expands to ~1.5 GB on disk.
  2. Cache it in CI too — the GitHub Action does this for you; for other CI systems, cache the directory CODEWARD_CACHE_DIR points at.
  3. Install dependencies — run npm ci, pip install before scanning
  4. Air-gapped mode--intel-mode local against a pre-seeded cache
  5. Use a key for large monoreposapi mode skips the snapshot download entirely
  6. Limit glob scope — narrow file patterns reduce scan time
  7. Pin image versions — use ghcr.io/codeward-io/scan:v0.4.0

Exit Codes

CodeMeaning
0Success — no blocking findings
1Failure — block action triggered, no vulnerability data obtained, or fatal error

Security Notes

  • All scanning runs inside the container — no code leaves the runner
  • Outputs go only to configured destinations
  • The only outbound calls are to Codeward Intel (snapshot downloads or API queries), package registries for licence resolution, and your own url: destinations
  • Snapshot manifests are Ed25519-signed and verified before any segment is trusted
  • The scanner sends no scan data back to Codeward; see Telemetry & Privacy
  • Use repository-scoped tokens with minimal permissions
  • Grant only: contents: read, packages: read, pull-requests: write, issues: write