Reference
Environment Variables
All FlexLock environment variables are prefixed with FLEXLOCK_.
Parallel Execution
Variable |
Type |
Default |
Description |
|---|---|---|---|
|
int |
|
Poll interval in seconds for checking task status |
|
int |
|
Log frequency in seconds for progress updates |
|
int |
|
Default number of parallel jobs |
|
int |
|
Default timeout in seconds for HPC jobs |
Smart Run / Caching
Variable |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
|
Warn when |
|
path |
(auto) |
Explicit path to the project-wide fingerprint index DB. Overrides auto-discovery. |
|
bool |
|
On an index miss, fall back to the legacy |
Project-wide fingerprint index. smart_run cache hits are served from a
derived SQLite index that maps a run fingerprint (config + code tree hashes +
data hashes) to where a completed run lives — a run.lock directory or a
sweep task (task_db, task_id). This makes sweep items first-class: a config
first run as a sweep task is a cache hit when re-run serially, and vice-versa.
Only successful (status='done') runs are ever served.
The index is a derived cache — run.lock stays authoritative and the index
can always be deleted and rebuilt with flexlock reindex <dir>. Its location is
resolved as: $FLEXLOCK_INDEX → the nearest .flexlock/index.db walking up
from each search_dir (skipping $HOME/tmp/filesystem-root) →
<results_root>/.flexlock/index.db. For hits to land, the read and write paths
must resolve to the same file — a project wrapper should set search_dirs (and,
if needed, $FLEXLOCK_INDEX) so they agree. Auto-indexing is skipped when a run
has no project context (its index would sit directly in $HOME/tmp/root).
Data Hashing
Variable |
Type |
Default |
Description |
|---|---|---|---|
|
path |
|
Base dir for the data-hash cache (stored under |
|
bool |
|
Force-disable hash caching (overrides a |
|
int |
|
Max files to hash in a directory before warning |
|
int |
|
Override file limit for cache operations |
Timestamp Format
Variable |
Type |
Default |
Description |
|---|---|---|---|
|
str |
|
Format for directory timestamps |
Logging
Variable |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
|
Whether to configure logging by default |
Debug Mode
Variable |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
|
Enable debug mode (drops into debugger on error) |
|
bool |
|
Disable debug mode (takes precedence over |
|
str |
|
Debug strategy: |
Debug strategies:
auto: Detect environment - use PDB for scripts, inject locals for notebooks/interactivepdb: Always use PDB post-mortem debuggerinject: Always inject locals into caller’s namespace (for notebooks)
Boolean Values
Boolean environment variables accept:
True:
1,true,yes,onFalse:
0,false,no,off
Exceptions
FlexLock defines a hierarchy of exceptions for error handling.
Exception Hierarchy
FlexLockError (base)
├── FlexLockConfigError
├── FlexLockExecutionError
├── FlexLockSnapshotError
├── FlexLockValidationError
├── FlexLockCacheError
└── FlexLockBackendError
Exception Reference
FlexLockError
Base exception for all FlexLock errors. Catch this to handle any FlexLock-specific error.
from flexlock import FlexLockError
try:
result = proj.submit(cfg)
except FlexLockError as e:
print(f"FlexLock error: {e}")
FlexLockConfigError
Raised when there is an error in configuration.
Common causes:
Invalid configuration structure
Missing required keys
Invalid
_target_specificationOmegaConf interpolation errors
from flexlock import FlexLockConfigError
try:
cfg = proj.get('nonexistent_key')
except FlexLockConfigError as e:
print(f"Configuration error: {e}")
FlexLockExecutionError
Raised by FlexLock when execution machinery itself fails (for example, backend submission errors or task-database corruption).
Important: Exceptions raised inside the user’s target function are not wrapped — they propagate as the original exception type (e.g.
ValueError,RuntimeError). Useexcept Exceptionor the specific type if you need to catch them.FlexLockExecutionErroronly covers FlexLock-side failures around the call.
from flexlock import FlexLockExecutionError
try:
result = proj.submit(cfg)
except FlexLockExecutionError as e:
print(f"FlexLock failed to dispatch: {e}")
except ValueError as e:
print(f"User function raised: {e}")
FlexLockSnapshotError
Raised when there is an error creating or loading snapshots.
Common causes:
Cannot write to
save_dirCorrupted
run.lockfileGit repository errors during snapshot
Invalid data paths for hashing
from flexlock import FlexLockSnapshotError
try:
snapshot(cfg, repos={'main': '.'})
except FlexLockSnapshotError as e:
print(f"Snapshot error: {e}")
FlexLockValidationError
Raised when validation of inputs fails. Currently the main triggers are:
Per-item sweep
save_dirs that fall outside the sweep root.Sweep source ambiguity (multiple of
sweep/sweep_file/sweep_keygiven) or a missingsweep_key.Selection of a non-existent dotted key.
Numeric/range checks like n_jobs <= 0 are not enforced today —
that example would simply behave like n_jobs=1.
from flexlock import FlexLockValidationError
try:
proj.submit(cfg, sweep=[{'save_dir': '/elsewhere'}])
except FlexLockValidationError as e:
print(f"Validation error: {e}")
FlexLockCacheError
Raised when there is an error with smart run caching.
Common causes:
Cannot read cached
run.lockFingerprint comparison errors
Corrupted cache database
from flexlock import FlexLockCacheError
try:
result = proj.get_result(cfg, search_dirs=['outputs/'])
except FlexLockCacheError as e:
print(f"Cache error: {e}")
FlexLockBackendError
Raised when there is an error with HPC backends (Slurm/PBS).
Common causes:
Invalid backend configuration
Job submission failure
Queue/scheduler errors
Task database lock issues
from flexlock import FlexLockBackendError
try:
result = proj.submit(cfg, pbs_config='pbs.yaml')
except FlexLockBackendError as e:
print(f"HPC backend error: {e}")
Catching Multiple Exceptions
from flexlock import (
FlexLockError,
FlexLockConfigError,
FlexLockExecutionError,
)
try:
cfg = proj.get('train')
result = proj.submit(cfg)
except FlexLockConfigError as e:
print(f"Fix your configuration: {e}")
except FlexLockExecutionError as e:
print(f"Execution failed: {e}")
except FlexLockError as e:
print(f"Other FlexLock error: {e}")
On-Disk Run Files
A run directory is owned by RunRecord (flexlock/run_record.py). Every file is
written atomically (temp file + os.replace).
run.lock (YAML)
The snapshot written before execution — the human-editable record. Top-level
keys: timestamp, config (resolved), and optionally note, repos (git
tree/commit per tracked repo), data (data hashes), lineage (upstream runs),
fingerprint, parent.
timestamp: "2026-07-10T10:00:00"
note: "baseline before lr sweep" # only present when --note / note= was passed
config:
_target_: myproject.train.train
save_dir: outputs/exp/train
lr: 0.1
repos:
main: {commit: "abc…", tree: "def…", path: "/repo", is_dirty: false}
data: {train_csv: "xxh64:…"}
lineage:
extract: {path: "/abs/outputs/exp/extract", info: {...}}
fingerprint: "sha256:…"
note is metadata only — it is excluded from the fingerprint (which hashes
{config, repos, data}) and ignored by RunDiff, so it never affects caching.
run.complete (JSON)
Success marker written after the user function returns. A cache hit requires
both run.lock and run.complete. Writing it also clears any stale
run.error.
run.error (JSON, schema v1)
Failure sidecar written next to run.lock when the user function raises. Mirrors
the traceback the task DB also stores, so triage needs no sqlite. Capturing it
never masks the original exception (which still propagates unwrapped).
{"version": 1, "exc_type": "ValueError", "exc_message": "...",
"traceback": "full formatted chain", "timestamp": "ISO-8601",
"task_id": "optional (sweep)", "node": "optional (sweep)"}
KeyboardInterrupt is deliberately not captured — a bare run.lock with no
run.complete/run.error is the interrupted signature.
results.json (JSON)
The user function’s return payload ({"result": value} when it isn’t a dict).
For the JSON contracts of the query commands (show, graph, why), see
Agentic Workflows.