| name | nomos-compilation-debugging |
| description | Systematic debugging guide for Nomos compilation failures. Use this when compilation fails, providers won't start, references are unresolved, or builds produce unexpected output. |
Nomos Compilation Debugging
This skill provides a systematic approach to debugging Nomos compilation failures, from provider issues to reference resolution errors.
When to Use This Skill
nomos buildcommand fails with errors- Provider-related failures (not found, connection refused)
- Reference resolution errors (
unresolved reference) - Import cycle detection failures
- Unexpected compilation output or determinism issues
- Provider initialization or fetch errors
Diagnostic Process
Follow these steps in order for systematic troubleshooting:
Step 1: Identify Error Category
Compilation errors fall into these categories:
- Provider Errors - Provider binary issues, connection failures
- Reference Errors - Unresolved references, invalid paths
- Import Errors - Cycle detection, missing imports, parse failures
- Syntax Errors - Invalid .csl syntax
- Configuration Errors - Missing lockfile, invalid provider config
- Determinism Issues - Non-reproducible builds
Step 2: Check Provider Configuration
Verify Lockfile Exists
# Check for providers lockfile
ls -la .nomos/providers.lock.json
# If missing, run init:
nomos init config.csl
Expected lockfile structure:
{
"providers": [
{
"alias": "configs",
"type": "file",
"version": "0.2.0",
"os": "darwin",
"arch": "arm64",
"path": ".nomos/providers/file/0.2.0/darwin-arm64/provider",
"checksum": "sha256:..."
}
]
}
Verify Provider Binaries Installed
# Check provider directory structure
find .nomos/providers -type f -name "provider"
# Expected structure:
# .nomos/
# providers/
# file/
# 0.2.0/
# darwin-arm64/
# provider # Must be executable
# Verify binary is executable
ls -l .nomos/providers/file/0.2.0/darwin-arm64/provider
# Should show: -rwxr-xr-x (executable flag)
# If not executable:
chmod +x .nomos/providers/file/0.2.0/darwin-arm64/provider
Test Provider Binary Manually
# Run provider directly - should print PORT
.nomos/providers/file/0.2.0/darwin-arm64/provider
# Expected output: PORT=<number>
# If it crashes or prints errors, provider is broken
# Solution: Re-download with nomos init --force
Step 3: Debug Provider Connection Failures
Symptom: failed to start provider or connection refused
Check Provider Startup
# Enable verbose logging if available
# Run build with provider debugging
nomos build config.csl 2>&1 | tee build.log
# Look for:
# - "Starting provider: <alias>"
# - "Provider port: <port>"
# - Connection errors
Verify Provider Protocol
Provider must:
- Listen on
127.0.0.1(localhost only) - Print
PORT=<number>to stdout - Start gRPC server before returning
- Implement all required RPCs (Init, Fetch, Info, Health, Shutdown)
Test with minimal config:
source:
alias: 'test'
type: 'autonomous-bits/nomos-provider-file'
version: '0.2.0'
Step 4: Debug Reference Resolution Errors
Symptom: unresolved reference: reference:alias:path
Verify Source Declaration
Check that provider alias is declared:
source:
alias: 'configs' # Must match reference alias
type: 'autonomous-bits/nomos-provider-file'
version: '0.2.0'
app:
name: reference:configs:app.name # Alias must match
Verify Reference Path Exists
Test provider Fetch manually if possible:
# For file provider, verify file exists
ls -la ./data/app.name # or whatever the file path should be
Check Provider Init Configuration
Ensure provider receives correct configuration:
source:
alias: 'configs'
type: 'autonomous-bits/nomos-provider-file'
version: '0.2.0'
directory: './data' # Provider-specific config
Common Issues:
- Missing required config fields (e.g.,
directoryfor file provider) - Incorrect config types (string vs number)
- Relative paths that don't resolve correctly
Enable AllowMissingProvider Mode
For debugging, continue compilation without provider:
# This will show warnings but not fail
nomos build --allow-missing-provider config.csl
Step 5: Debug Import Errors
Symptom: cycle detected or failed to resolve import
Check Import Statements
Verify import syntax:
import:base:./base.csl # Correct format: import:<alias>:<path>
Detect Import Cycles
A imports B
B imports C
C imports A ← Cycle!
Solution: Refactor to break cycle
- Extract shared config to separate file
- Remove circular dependencies
- Use references instead of imports where possible
Verify Import Paths
# Check that imported files exist
ls -la ./base.csl
ls -la ./shared/common.csl
# Verify paths are relative to importing file or absolute
Step 6: Debug Syntax Errors
Symptom: Parse errors with line/column numbers
Read Error Messages Carefully
Parser errors show:
config.csl:15:3: SyntaxError: expected ':' after key
Location format: <file>:<line>:<column>
Common Syntax Mistakes
Missing colons:
# ❌ Wrong database host: localhost # ✅ Correct database: host: localhostInvalid reference syntax:
# ❌ Wrong app: reference:configs.app.name # ✅ Correct app: reference:configs:app.nameEmpty source alias:
# ❌ Wrong source: alias: '' # ✅ Correct source: alias: 'myalias'
Step 7: Debug Determinism Issues
Symptom: Same input produces different output on repeated builds
Test Reproducibility
# Build twice and compare
nomos build config.csl -o output1.json
nomos build config.csl -o output2.json
diff output1.json output2.json
# Should be identical (exit code 0)
Common Causes
Provider non-determinism: Provider returns different data
- Solution: Fix provider to be deterministic or use caching
Timestamp injection: Metadata includes timestamps
- Solution: Remove timestamps or make them optional
Map iteration order: Go maps iterate in random order
- Solution: Sort keys before serialization (compiler does this)
Concurrent provider fetches: Race conditions
- Solution: Enable provider caching (compiler does this)
Verify File Order
Nomos processes files in lexicographic order (UTF-8):
# Check file discovery order
find . -name "*.csl" -type f | sort
# Should match compilation order in build output
Step 8: Check Configuration Merge Behavior
Symptom: Unexpected values in final output
Understand Merge Semantics
Nomos deep-merge rules:
- Maps: Recursive merge, combining keys
- Scalars: Last-wins (newer value replaces older)
- Arrays: Last-wins (entire array replaced)
# base.csl
database:
host: localhost
port: 5432
# override.csl
import:base:./base.csl
database:
host: prod-server # Overrides localhost
# port: 5432 preserved from base
Trace Value Provenance
Enable metadata tracking if available to see where values came from.
Step 9: Verify Platform-Specific Issues
Symptom: Works on one OS/arch but not another
Check Provider Platform
Provider binaries are platform-specific:
# Verify correct binary for your platform
uname -sm
# Darwin arm64 → darwin-arm64
# Linux x86_64 → linux-amd64
# Check lockfile matches:
cat .nomos/providers.lock.json | grep -A 5 '"os"'
Cross-Platform Installation
Install providers for different platforms:
# Install for Linux on macOS development machine
nomos init --os linux --arch amd64 config.csl
# Then push .nomos/ directory to Linux CI
Common Error Messages and Solutions
"provider binary not found"
Cause: Provider not installed or wrong path in lockfile
Solution:
nomos init --force config.csl # Re-download
"connection refused"
Cause: Provider failed to start or wrong port
Solution:
- Test provider manually:
.nomos/providers/.../provider - Check provider prints
PORT=<number> - Verify provider doesn't exit immediately
"unresolved reference"
Cause: Reference path doesn't exist in provider data
Solution:
- Verify source alias matches reference
- Check provider configuration (e.g., directory path)
- Test provider data manually
- Use
--allow-missing-providerto debug
"cycle detected"
Cause: Circular import chain
Solution:
- Map import chain: A → B → C → A
- Extract shared config to break cycle
- Use references instead of imports
"invalid checksum"
Cause: Provider binary modified or corrupted
Solution:
# Re-download provider
nomos init --force config.csl
# Or manually verify checksum
shasum -a 256 .nomos/providers/.../provider
# Compare with lockfile checksum
Advanced Debugging
Enable Verbose Logging
If Nomos supports verbose mode:
nomos build -v config.csl # Verbose output
nomos build -vv config.csl # Very verbose (debug level)
Inspect Provider gRPC Communication
Use gRPC debugging tools if needed:
# Find provider port
ps aux | grep provider
# Connect with grpcurl (if provider running)
grpcurl -plaintext localhost:<port> list
grpcurl -plaintext localhost:<port> nomos.provider.v1.ProviderService/Info
Test Components Individually
- Parse only: Verify .csl syntax
- Init only: Test provider installation
- Build without providers: Use
--allow-missing-provider - Build single file: Isolate problematic config
Prevention Best Practices
- Commit lockfile: Check
.nomos/providers.lock.jsoninto git - Pin versions: Use explicit version in source declarations
- Test providers: Verify provider works before using in config
- Validate syntax: Use editor tooling for .csl files
- Run CI builds: Catch determinism issues early
- Document references: Comment expected provider data structure
Reference Documentation
For more details, see: