You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
When jig returns Windows paths like C:\Users\Dmitri\..., the ArgumentFiles.parse() method treats backslashes as escape characters
#72
The ja tool has a bug in its argument parser (ArgumentFiles.java). When jig returns Windows file paths like C:\Users..., the parser treats each backslash () as an escape character and strips it out, resulting in corrupted paths like C:Users.... Java then fails to find your module.
What needs to be changed to make the fix permanent?
This requires a code fix from Netflix:
NB! Fixes are suggested by Claude Code
Option 1: Fix jig (Recommended)
jig should escape backslashes when outputting paths on Windows:
Current output: C:\Users\Dmitri...
Should output: C:\Users\Dmitri\... (escaped)
OR: C:/Users/Dmitri/... (forward slashes work on Windows)
Here are practical fixes the ja maintainers can implement in ArgumentFiles.java:
Option 2: Smart Escape Handling (Recommended)
Only treat \ as an escape when followed by a valid escape character:
public static List<String> parse(String content) {
var arguments = new ArrayList<String>();
var current = new StringBuilder();
boolean quoted = false;
boolean started = false;
for (int i = 0; i < content.length(); i++) {
char character = content.charAt(i);
if (character == '\\' && i + 1 < content.length()) {
char next = content.charAt(i + 1);
// Only treat as escape if followed by valid escape characters
if (next == '\\' || next == '"' || next == 'n' || next == 't' || next == 'r') {
i++; // Skip the backslash
current.append(switch (next) {
case 'n' -> '\n';
case 't' -> '\t';
case 'r' -> '\r';
default -> next; // For \\ and \"
});
started = true;
} else {
// Not a valid escape sequence, treat as literal backslash
current.append(character);
started = true;
}
} else if (character == '"') {
quoted = !quoted;
started = true;
} else if (Character.isWhitespace(character) && !quoted) {
if (started) {
arguments.add(current.toString());
current.setLength(0);
started = false;
}
} else {
current.append(character);
started = true;
}
}
if (quoted) {
throw new IllegalArgumentException("Malformed argument file");
}
if (started) {
arguments.add(current.toString());
}
return List.copyOf(arguments);
}
Why this works:
C:\Users → \U is not a valid escape, so keep both \ and U → C:\Users ✅
C:\Users → \ IS valid escape → C:\Users ✅
"test\n" → \n IS valid escape → "test" ✅
Option 3: Platform-Aware Parsing
Disable backslash escaping on Windows entirely:
private static final boolean IS_WINDOWS =
System.getProperty("os.name").startsWith("Windows");
public static List<String> parse(String content) {
return IS_WINDOWS ? parseWindows(content) : parseUnix(content);
}
private static List<String> parseWindows(String content) {
var arguments = new ArrayList<String>();
var current = new StringBuilder();
boolean quoted = false;
boolean started = false;
for (int i = 0; i < content.length(); i++) {
char character = content.charAt(i);
if (character == '"') {
quoted = !quoted;
started = true;
} else if (Character.isWhitespace(character) && !quoted) {
if (started) {
arguments.add(current.toString());
current.setLength(0);
started = false;
}
} else {
current.append(character); // No escape handling on Windows
started = true;
}
}
if (quoted) {
throw new IllegalArgumentException("Malformed argument file");
}
if (started) {
arguments.add(current.toString());
}
return List.copyOf(arguments);
}
private static List<String> parseUnix(String content) {
// Original implementation with escape handling
// ...
}
Pros: Simple, fixes Windows immediately
Cons: Can't use escape sequences on Windows (but who needs \n in paths?)
Option 4: Path Validation & Recovery
Detect corrupted paths and warn/fix them:
public static List<String> parse(String content) {
// ... existing parse logic ...
// Validate and fix paths
return arguments.stream()
.map(ArgumentFiles::validatePath)
.toList();
}
private static String validatePath(String arg) {
// Detect Windows path patterns that got corrupted
// e.g., "C:Users" should be "C:\Users"
if (System.getProperty("os.name").startsWith("Windows")) {
// Pattern: Drive letter + colon + no backslash + path
if (arg.matches("^[A-Za-z]:[^\\\\].*")) {
System.err.println(
"WARNING: Detected corrupted Windows path: " + arg);
System.err.println(
"This is likely due to unescaped backslashes from jig.");
System.err.println(
"Please report this bug to: https://github.com/Netflix/ja/issues");
}
}
return arg;
}
Pros: Helps users understand the problem
Cons: Can't actually fix the path (data is already lost)
Option 5: Different Protocol (Long-term)
Replace the text-based protocol with structured data:
// In ModuleResolver.java, change how jig output is parsed
private List<String> run(List<String> arguments, InputStream in, PrintStream err) {
var outputBytes = new ByteArrayOutputStream();
int exitCode;
try (var output = new PrintStream(outputBytes, true, StandardCharsets.UTF_8)) {
exitCode = tools.resolveModules(in, output, err, arguments.toArray(String[]::new));
}
if (exitCode != 0) {
throw new ToolExecutionException(exitCode);
}
// NEW: Check if jig supports JSON output
String outputStr = outputBytes.toString(StandardCharsets.UTF_8);
if (outputStr.trim().startsWith("{")) {
return parseJson(outputStr);
} else {
// Fallback to argument-file format
return ArgumentFiles.parse(outputStr);
}
}
private List<String> parseJson(String json) {
// Parse JSON format from jig
// { "arguments": ["--module-path", "C:\\Users\\...", ...] }
}
The original problem
The Original Failed Command when executed on WIndows 11:
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The ja tool has a bug in its argument parser (ArgumentFiles.java). When jig returns Windows file paths like C:\Users..., the parser treats each backslash () as an escape character and strips it out, resulting in corrupted paths like C:Users.... Java then fails to find your module.
What needs to be changed to make the fix permanent?
This requires a code fix from Netflix:
NB! Fixes are suggested by Claude Code
Option 1: Fix jig (Recommended)
jig should escape backslashes when outputting paths on Windows:
Here are practical fixes the ja maintainers can implement in ArgumentFiles.java:
Option 2: Smart Escape Handling (Recommended)
Only treat \ as an escape when followed by a valid escape character:
Why this works:
Option 3: Platform-Aware Parsing
Disable backslash escaping on Windows entirely:
Pros: Simple, fixes Windows immediately
Cons: Can't use escape sequences on Windows (but who needs \n in paths?)
Option 4: Path Validation & Recovery
Detect corrupted paths and warn/fix them:
Pros: Helps users understand the problem
Cons: Can't actually fix the path (data is already lost)
Option 5: Different Protocol (Long-term)
Replace the text-based protocol with structured data:
The original problem
The Original Failed Command when executed on WIndows 11:
ja --verbose run
What jig outputs (correct):
[resolve jig --verbose --module-source-path "demo=D:\Workspaces\Java\Learning\ja-demo" ...]
Notice: D:\Workspaces\... (properly escaped for argument-file format)
What ja executes (CORRUPTED):
[execute java --module-path C:UsersDmitriAppDataLocalcom.netflix.tools.jigmodulesdemoconfiguration533c9017216452947606d026ab9ef69cd15a69d2fa2ba33666aa1b7a3789fb53base2b4fe7c8ad9eca881dcec4477086fa01ed72054c24c533d56882e9fd5a59fc35 --add-modules demo --module demo/demo.Main]
The Smoking Gun:
Look at the --module-path:
C:UsersDmitriAppDataLocalcom.netflix.tools.jig...
^ ^ ^ ^ ^
All backslashes are GONE! Should be:
C:\Users\Dmitri\AppData\Local\com.netflix.tools.jig...
The Error:
Error occurred during initialization of boot layer
java.lang.module.FindException: Module demo not found
Java can't find the module because the path C:UsersDmitri... doesn't exist. It's looking for a path that doesn't have directory separators!
Contrast with Working Command:
When you call jig directly:
jig --module-source-path "demo=$(pwd)" -m demo --resolve-options module-path,module=main
Output:
--module-path
C:\Users\Dmitri\AppData\Local\com.netflix.tools.jig\modules\demo\complete...
--module
demo/demo.Main
Notice the backslashes are preserved! That's because you're reading it directly, not parsing it through ArgumentFiles.parse().
This is the definitive proof that ArgumentFiles.parse() is stripping the backslashes from jig's output.
All reactions