Troubleshooting

Start with paf doctor. It checks git, Node, the pins, every unit's layout, the SDK, and the workflows in one go, and names what to fix. paf status then shows where each unit stands.

Every message below is quoted as paf prints it, with the unit and face names from an example repo. A command that stops prints its message after paf:. One that runs over several units prints each unit's problem after the unit's name, then a closing line such as sync failed in watchfaces/mosaic.

The Tag Moved

watchfaces/mosaic: v4.0.0 now points at <new commit>, but mosaic/paf.config.json recorded <old commit>. If the move is expected, run paf pin mosaic v4.0.0 to take it

The framework tag the unit pins was moved to another commit after the unit recorded it. paf stops rather than quietly build against a framework nobody chose. If the move is expected, run the paf pin it names, which records the new commit. Then commit paf.config.json.

A Framework 3 Pin

watchfaces/mosaic: mosaic/paf.config.json pins v3.0.0, which is framework 3 and needs paf 1.0.0. This paf fills framework 4, so move the unit to a framework 4 tag with paf pin

paf 2.0.0 only fills framework 4. Move the unit with paf pin mosaic latest once its faces are ready for framework 4, or keep paf 1.0.0 for it until then.

paf pin refuses a framework 3 tag the same way, and lists the framework 4 tags it would take.

node_modules from the Other System

paf: watchfaces/mosaic/node_modules was installed from linux, and its native packages only run there. Run paf sync --force to reinstall it for win32, which breaks it for the other one

The unit was installed from WSL and this command ran on Windows, or the other way round. Run paf sync --force on the system you want to use. See Switching between WSL and Windows.

The Workspaces Are Missing

paf: watchfaces/mosaic/package.json does not list paf/plugins/* in its workspaces, so npm never installs the plugins' packages. Make it "workspaces": ["paf", "paf/plugins/*"]
paf: watchfaces/mosaic has no package.json, so npm would install into the folder above it. Give it one with "workspaces": ["paf", "paf/plugins/*"]

Every unit needs its own package.json listing both workspaces. See package.json.

A paf/ That paf Did Not Fill

paf: /work/pebble-watchfaces/watchfaces/mosaic/paf holds a framework paf did not put there. Remove it first, with git rm paf for a submodule

paf/ already holds files paf has no record of filling, such as a framework mounted there by hand as a git submodule. It could hold uncommitted work, so paf leaves it for you to remove. Run git rm paf in the unit for a submodule, or move the folder away, then sync.

paf sync --locked Refuses

--locked never writes paf.config.json or the lock, so anything it would have to write stops it instead.

watchfaces/mosaic: watchfaces/mosaic has no package-lock.json, and --locked writes none

Run paf sync once without --locked and commit the lock it writes.

watchfaces/mosaic: mosaic/paf.config.json records no commit for v4.0.0, and --locked writes none. Run paf pin mosaic v4.0.0

Run the paf pin it names and commit paf.config.json.

pebble-watchface-lcars: ./paf is on the local framework at /home/me/src/pebble-app-framework, not its pinned tag. Run paf use pebble-watchface-lcars pinned first

The unit is on a local framework from paf use. Put it back with paf use <unit> pinned.

When npm ci itself fails, the lock is out of step with a package.json. Run paf sync without --locked, then commit the updated package-lock.json.

A Plugin Is Missing

paf: the unit lists the plugin frames, which v4.0.0 does not have. It has code-style, dev, frame, icons, and thumbnails

The unit lists a plugin the tag does not have, or misspells one. Fix the name under plugins, or move to a tag that has it.

paf: no generator called background. The frame plugin offers it, so list it under plugins in paf.config.json and run paf sync

The generator or tool comes from a plugin the unit does not list. Add it under plugins and run paf sync. See Adding a Plugin.

The Wrong Node

watchfaces/mosaic: paf/package.json asks for Node ^22.18.0 || >=24.2.0, and this is 23.1.0. Outside it a tool can stop partway, or stop before it starts, so run paf from a Node inside it

The framework's tools only run inside the Node range its package.json names. Switch to a Node inside it, such as the newest 24. paf itself runs on Node 23, so sync, status, and pin still work there.

An Appinfo Left in config/

paf: watchfaces/mosaic/gridlock/config/pebble.appinfo.json is where framework 3 keeps an appinfo. Move each up a folder, beside the face's src/, since framework 4 finds a face by the pebble.appinfo.json at its own root

Framework 4 finds a face by the pebble.appinfo.json at its own root. Move each one named up a folder.

Files Left from paf 1.0.0

paf: watchfaces/mosaic still has a paf.json, which paf 1.0.0 reads. This paf reads paf.config.json. Move each unit by hand, then delete its paf.json

paf 2.0.0 reads paf.config.json instead. Move the settings across by hand, then delete paf.json. Every command stops until each one is gone, so a repo half moved never syncs some units and not others.

paf doctor also finds a lib/ that paf 1.0.0 filled:

problem  watchfaces/mosaic/lib is left from paf 1.0.0, which filled it. Delete it, since paf 2.0.0 fills paf/

Workflows on an Older Framework

problem  .github/workflows/ci.yml loads the framework's actions at v3.0.0, older than v4.0.0. Move them to @v4.0.0

A workflow loads the framework's actions, such as setup-pebble, at a tag older than the newest one a unit pins. Move each @ to the tag paf doctor names.

An Older SDK

behind   SDK 4.32.0 is older than 4.33.1, which v4.0.0 was built with (mosaic)

The SDK pebble reports is older than the one the framework tag was built and tested with. Install the SDK it names with pebble sdk install. A newer SDK is only a note.

Names That Clash

paf: two units are named mosaic, at watchfaces/mosaic and watchapps/mosaic. Rename one of the folders
paf: two faces are named gridlock, in watchfaces/mosaic and watchfaces/gridlock. A face's name has to be unique in the repo

Commands take a unit or a face by name alone, so every name has to point at one place. Rename one of the folders, or the name in a face's appinfo.

Nothing Found

paf: this is not inside a git repo. Run paf from a face repo

paf works on the git repo it runs inside. Change into the face repo first.

paf: no units here. A unit is a folder with a paf.config.json holding { "framework": "<tag>" }, at the repo root or under watchfaces/ or watchapps/

The repo has no paf.config.json where paf looks. See Where Units Sit.

paf: no unit or face called gridlok. Run paf status for the units here

The name is misspelled, or the face is in a unit whose appinfo could not be read, which the message then names. paf status lists every unit and face.

TypeScript Not Found

watchfaces/mosaic has no typescript installed. Delete its node_modules and run paf sync mosaic

paf typecheck runs the TypeScript the unit installed, and found none inside the unit. Do what the message says.

A paf Too Old for the Framework

paf: toolchain.json is format 2, which this paf does not read. Update paf

The framework tag is newer than this paf understands. Install the latest paf release, as under Install.