raccoon validate

raccoon validate [--no-python-compile]

Checks that your project’s configuration and source files are internally consistent. Use it to catch drift between raccoon.project.yml, mission files, and src/main.py before running on the robot.

When validation runs

raccoon validate runs automatically before every command except the exempt list below. You rarely need to call it explicitly — it is already protecting you on every raccoon run and raccoon sync. The explicit command is useful when you want to check consistency without triggering a run.

exempt (no auto-validation): validate, create, connect, disconnect, update, doctor, migrate, web

Why it exists

As a project grows — missions are added, renamed, moved, or deleted — it is easy for raccoon.project.yml and the file system to drift out of sync. A mission listed in config but missing on disk will cause a runtime failure; a mission file on disk that is not listed in config will silently never run. raccoon validate catches these mismatches ahead of time, in your terminal, before you waste time syncing and running.

Synopsis

raccoon validate                     # full validation including Python compile
raccoon validate --no-python-compile # skip bytecode compile (faster)
FlagTypeDefaultDescription
--no-python-compileflagoffSkip Python syntax check. All other checks still run. Useful when your environment does not match the robot’s Python version.

What it checks

raccoon validate runs five categories of checks:

CheckSeverityWhat it looks for
Required config keysERRORname and uuid must be present and non-empty in raccoon.project.yml
Config → filesERROREvery mission class name in missions: must have a matching file at src/missions/<snake>_mission.py
Files → configWARNINGEvery m???_*_mission.py file under src/missions/ must be listed in missions:
main.py importsERROR / WARNINGEvery from .missions.<module> import <Class> in src/main.py must resolve to a file that exists and a class that is in config
Python compileERROREvery .py file under src/ must be free of syntax errors (py_compile)

ERRORs abort the command with exit code 1. WARNINGs are printed but do not fail.

The naming convention the checker enforces is:

  • Class name M030HelloMission → file src/missions/m030_hello_mission.py
  • File src/missions/m030_hello_mission.py → expected class M030HelloMission

Output examples

Clean project

✓ Project is consistent — no issues found.

Project with issues

⚠ 'src/missions/m040_obstacle_mission.py' exists but 'M040ObstacleMission' is not in config
  Add 'M040ObstacleMission' to raccoon.project.yml or delete the file

✗ Mission 'M050ReturnMission' is in config but 'm050_return_mission.py' does not exist
  Create the file or remove 'M050ReturnMission' from raccoon.project.yml

1 error(s) found. Fix them before proceeding.

Automatic pre-command validation

raccoon validate does not only run when you call it explicitly. The CLI automatically runs a validation pass before every command, unless that command is in the exempt list.

The exempt commands (no auto-validation) are:

validate, create, connect, disconnect, update, doctor, migrate, web

If the project has validation errors, the auto-validation prints the issues and aborts with exit code 1 before the requested command runs. This prevents you from syncing a broken project to the Pi.

Bypassing auto-validation

To skip the automatic pre-command validation for a single invocation, use the global --no-validate flag before the subcommand:

raccoon --no-validate run          # run without validating first
raccoon --no-validate sync         # sync without validating first
raccoon --no-validate codegen      # regenerate code without validating

--no-validate is a flag on the top-level raccoon command, not on the subcommand. It must appear before the subcommand name.

This is useful when:

  • You are mid-refactor and know the project is temporarily inconsistent.
  • You want to run codegen to see what it produces before cleaning up missions.
  • The Python compile check flags a version-specific syntax that works on the Pi but not locally.

Common issues and fixes

MessageCauseFix
Missing required project key: 'uuid'uuid: is blank or absent in raccoon.project.ymlAdd a UUID: python3 -c "import uuid; print(uuid.uuid4())" and paste it
Mission 'M030Foo' is in config but 'm030_foo_mission.py' does not existMission was deleted from disk but not removed from missions:Remove the entry from raccoon.project.yml, or recreate the file with raccoon create mission
'src/missions/m030_foo_mission.py' exists but 'M030FooMission' is not in configFile created manually or left over after a renameAdd the class to missions: in raccoon.project.yml, or delete the file
main.py imports '...' but '...' does not existImport in main.py references a deleted or renamed missionUpdate or remove the import in src/main.py
Syntax error in src/missions/m030_foo_mission.pyPython syntax error in the named fileOpen the file and fix the syntax error shown in the message