Describe the bug
Prefab fails with Error: no such option when a <package_path> positional argument contains an = character. Clikt's argument parser interprets the text before = as an option name (e.g. --patch_hash=abc123), even though the token is a positional argument, not an option.
This breaks all pnpm users who have patched dependencies, because pnpm encodes patch hashes in directory names:
node_modules/.pnpm/react-native-reanimated@4.1.0_patch_hash=f8d3886b.../
When AGP invokes prefab via GeneratePrefabPackages.kt, these paths are passed as positional <package_path> arguments without a preceding --, causing the parse failure.
To Reproduce
- Create a minimal prefab package:
mkdir -p /tmp/repro/pkg/modules/test/libs/android.arm64-v8a
echo '{"schema_version": 2, "name": "test", "version": "1.0.0", "dependencies": []}' \
> /tmp/repro/pkg/prefab.json
echo '{"export_libraries": [], "android": {"export_libraries": [], "library_name": null}}' \
> /tmp/repro/pkg/modules/test/module.json
echo '{"abi": "arm64-v8a", "api": 24, "ndk": 27, "stl": "c++_shared"}' \
> /tmp/repro/pkg/modules/test/libs/android.arm64-v8a/abi.json
touch /tmp/repro/pkg/modules/test/libs/android.arm64-v8a/libtest.so
- Copy it to a path containing
=:
mkdir -p "/tmp/repro/some-lib@1.0.0_patch_hash=abc123"
cp -r /tmp/repro/pkg "/tmp/repro/some-lib@1.0.0_patch_hash=abc123/pkg"
- Run prefab with the
=-containing path as a positional argument:
java -jar prefab-cli-2.1.0-all.jar \
--build-system cmake --platform android --abi arm64-v8a \
--os-version 24 --stl c++_shared --ndk-version 27 \
--output /tmp/repro/out \
"/tmp/repro/some-lib@1.0.0_patch_hash=abc123/pkg"
Expected behavior
Prefab should treat the path as a positional <package_path> argument and process it normally, regardless of whether the path contains =.
Logs
Usage: prefab [<options>] <package_path>...
Error: no such option /tmp/repro/some-lib@1.0.0_patch_hash
Adding -- before the positional arguments works around the issue:
java -jar prefab-cli-2.1.0-all.jar \
--build-system cmake --platform android --abi arm64-v8a \
--os-version 24 --stl c++_shared --ndk-version 27 \
--output /tmp/repro/out \
-- "/tmp/repro/some-lib@1.0.0_patch_hash=abc123/pkg"
# exits 0
Environment:
Prefab version: 2.1.0
Host OS: macOS 26.3.1 (also reproduces on Linux EAS build workers)
Target platform: android
Target ABI: arm64-v8a
Target OS version: 24
Build system: cmake
Additional context
The root cause is in Cli.kt where PACKAGE_PATH is declared as a clikt argument():
private val rawPackagePaths: List<File> by argument("PACKAGE_PATH").file(
canBeFile = false, mustBeReadable = true
).multiple(required = true)
Clikt treats any token containing = as --option=value syntax before considering positional arguments.
This affects pnpm monorepo users with React Native + New Architecture. pnpm appends patch_hash=<hex> to directory names when a package is patched. Since react-native is commonly patched, every native library that depends on it gets = in its resolved path. AGP's GeneratePrefabPackages.kt passes these paths without --:
.addArgs(prefabPackages.map { it.packageFolder.path })
Suggested fix (either one):
- In prefab: Insert
-- before the PACKAGE_PATH arguments in the argument parser, or configure clikt to not interpret = in positional tokens.
- In AGP: Add
.addArgs("--") before .addArgs(prefabPackages.map { it.packageFolder.path }) in GeneratePrefabPackages.kt.
Previously reported (and closed without fix) at:
Describe the bug
Prefab fails with
Error: no such optionwhen a<package_path>positional argument contains an=character. Clikt's argument parser interprets the text before=as an option name (e.g.--patch_hash=abc123), even though the token is a positional argument, not an option.This breaks all pnpm users who have patched dependencies, because pnpm encodes patch hashes in directory names:
When AGP invokes prefab via
GeneratePrefabPackages.kt, these paths are passed as positional<package_path>arguments without a preceding--, causing the parse failure.To Reproduce
=:=-containing path as a positional argument:java -jar prefab-cli-2.1.0-all.jar \ --build-system cmake --platform android --abi arm64-v8a \ --os-version 24 --stl c++_shared --ndk-version 27 \ --output /tmp/repro/out \ "/tmp/repro/some-lib@1.0.0_patch_hash=abc123/pkg"Expected behavior
Prefab should treat the path as a positional
<package_path>argument and process it normally, regardless of whether the path contains=.Logs
Adding
--before the positional arguments works around the issue:Environment:
Prefab version: 2.1.0
Host OS: macOS 26.3.1 (also reproduces on Linux EAS build workers)
Target platform: android
Target ABI: arm64-v8a
Target OS version: 24
Build system: cmake
Additional context
The root cause is in
Cli.ktwherePACKAGE_PATHis declared as a cliktargument():Clikt treats any token containing
=as--option=valuesyntax before considering positional arguments.This affects pnpm monorepo users with React Native + New Architecture. pnpm appends
patch_hash=<hex>to directory names when a package is patched. Sincereact-nativeis commonly patched, every native library that depends on it gets=in its resolved path. AGP'sGeneratePrefabPackages.ktpasses these paths without--:.addArgs(prefabPackages.map { it.packageFolder.path })Suggested fix (either one):
--before thePACKAGE_PATHarguments in the argument parser, or configure clikt to not interpret=in positional tokens..addArgs("--")before.addArgs(prefabPackages.map { it.packageFolder.path })inGeneratePrefabPackages.kt.Previously reported (and closed without fix) at: