pprotect "Protected file not found" error when run via poetry -C
pprotect fails with "Protected file not found" (surfacing as Failed to get protected credentials: Expecting value: line 1 column 1 (char 0)) only when a Python script is launched via poetry -C <subdir> run python script.py. The same credential code path succeeds through the project's own CLI entrypoint and succeeds when pprotect is run by hand from the repo root.
Root cause
Two things compose:
poetry -C <subdir> runsets the child process CWD to<subdir>, not the directory you invoked poetry from.pprotectresolvesprotected.yamlrelative to CWD and does not walk up. With CWD now<repo>/fsrv, it looks for<repo>/fsrv/protected.yaml, which does not exist.
The project's own CLI entrypoint was immune because it chdirs to the repo root while loading config, so every prior caller masked the bug.
The error message is opaque because the wrapper does json.loads(result.stdout) on a subprocess.run(..., capture_output=True) result with no check=True and no returncode inspection. pprotect exits rc=2 and writes error: Protected file not found: <path> to stderr, leaving stdout empty, so the caller reports a JSON decode error instead of the real one.
Diagnosis
Replicate the exact subprocess call and print rc + stderr:
import os, subprocess
r = subprocess.run(['pprotect','decrypt-domain','--non-interactive','biz'],
capture_output=True, text=True,
env={'PATH': os.environ['PATH'],
'PPROTECT_USER': u, 'PPROTECT_PASSPHRASE': p})
print(r.returncode, repr(r.stdout[:200]), repr(r.stderr[:400]))rc=2, stdout='', stderr='error: Protected file not found: /repo/fsrv/protected.yaml\n' names it immediately.
Fix
Invoke the venv interpreter directly with the shell CWD at the repo root, instead of going through poetry -C:
cd /path/to/repo
"$(poetry -C fsrv env info --path)/bin/python" myscript.pyAlternatives: cd repo && poetry run python myscript.py (no -C), or os.chdir(repo_root) at the top of the script before any credential read.
Generalizable lesson
Any CWD-relative resource (secrets vault, config file, relative symlink, data dir) breaks under poetry -C <subdir> run, and it breaks only for entrypoints that don't already chdir, which makes it look intermittent. Separately: when a credential helper strips the parent environment (env={'PATH':..., ...}) and then json-decodes stdout, always check returncode and surface stderr, or every failure mode collapses into the same useless "Expecting value: line 1 column 1".