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:
nomos# ❌ Wrong database host: localhost # ✅ Correct database: host: localhost
- •
Invalid reference syntax:
nomos# ❌ Wrong app: reference:configs.app.name # ✅ Correct app: reference:configs:app.name
- •
Empty source alias:
nomos# ❌ 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: