Skip to content

Local dev server fails to start #506

Description

@zdenda

Starting the local development server (DevAppServer / Gradle appengineStart) fails with exception:

com.google.appengine.tools.development.jetty.JettyContainerService startHotDeployScanner
INFO: Full scan of the web app in place every 1s.
java.lang.RuntimeException: java.lang.IllegalArgumentException: 'maxDepth' is negative
	at org.eclipse.jetty.util.component.LifeCycle.start(LifeCycle.java:59)
	at com.google.appengine.tools.development.jetty.JettyContainerService.fullWebAppScanner(JettyContainerService.java:527)
	at com.google.appengine.tools.development.jetty.JettyContainerService.startHotDeployScanner(JettyContainerService.java:429)
	at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:286)
	at com.google.appengine.tools.development.AutomaticInstanceHolder.startUp(AutomaticInstanceHolder.java:42)
	at com.google.appengine.tools.development.AbstractModule.startup(AbstractModule.java:101)
	at com.google.appengine.tools.development.Modules.startup(Modules.java:133)
	at com.google.appengine.tools.development.DevAppServerImpl.doStart(DevAppServerImpl.java:275)
	at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:228)
	at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:383)
	at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:58)
	at com.google.appengine.tools.development.DevAppServerMain.run(DevAppServerMain.java:239)
	at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:230)
Caused by: java.lang.IllegalArgumentException: 'maxDepth' is negative
	at java.base/java.nio.file.FileTreeWalker.<init>(FileTreeWalker.java:188)
	at java.base/java.nio.file.Files.walkFileTree(Files.java:2791)
	at org.eclipse.jetty.util.Scanner.scanFiles(Scanner.java:832)
	at org.eclipse.jetty.util.Scanner.startScanning(Scanner.java:711)
	at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:678)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:92)
	at org.eclipse.jetty.util.component.LifeCycle.start(LifeCycle.java:55)
	... 12 more
Caused by: java.lang.IllegalArgumentException: 'maxDepth' is negative

Environment

  • Google Cloud SDK: 572.0.0 (Last working SDK: 568.0.0)
  • Runtime: java17
  • Build tool: com.google.cloud.tools.appengine-appenginewebxml Gradle plugin, appengineStart
  • OS: Windows 11

AI Analysis of this issue (Take this with a grain of salt, but it might help)

Introduced by: fcc24ef#diff-6451d30fd34f0beafb3ec7f80d2acc7ffa27f634727bb7ce71a4437cf7cf4623R516

Summary

Starting the local development server (DevAppServer / Gradle appengineStart) fails immediately when full-scan hot-reload is active, because JettyContainerService.fullWebAppScanner(int) calls scanner.setScanDepth(-1). Jetty 12.1's Scanner passes that value straight to Files.walkFileTree(...), which throws IllegalArgumentException: 'maxDepth' is negative. The comment // -1 means unlimited depth. reflects an old Jetty 9 API contract that no longer holds for the Jetty 12.1 Scanner.

Root cause

runtime/local_jetty121/.../jetty/JettyContainerService.java (current main, line 516):

scanner.setScanDepth(-1); // -1 means unlimited depth.

Jetty's Scanner.scanFiles() (Scanner.java:832) does:

Files.walkFileTree(root, options, _scanDepth, visitor);

and Files.walkFileTree mandates maxDepth >= 0, throwing IllegalArgumentException otherwise. Jetty's Scanner has used the native walkFileTree(maxDepth) form for a long time (the file is byte-identical between jetty-12.1.8 and jetty-12.1.10), so -1 was never valid on Jetty 12.1 — only the older Jetty 9 Scanner tolerated it as "unlimited".

Regression origin

Introduced by commit fcc24ef (2026-05-06):

"Modified JettyContainerService.java to set the file scanner depth to unlimited (-1) in the local development server. This was an ancient regression after removing Jetty9 where the API was different."

It changed setScanDepth(3)setScanDepth(-1). Verified via bytecode of the shipped runtime jars:

  • SDK 568 JettyContainerService.fullWebAppScanner: iconst_3setScanDepth(3) (works)
  • SDK 572 JettyContainerService.fullWebAppScanner: iconst_m1setScanDepth(-1) (throws)

Note the EE11 variant (local_jetty121_ee11/.../JettyContainerService.java) correctly uses setScanDepth(3); only the EE8 local_jetty121 path regressed.

Suggested fix

Use a valid non-negative depth. Jetty's documented "unlimited" value is Integer.MAX_VALUE:

scanner.setScanDepth(Integer.MAX_VALUE); // unlimited; Jetty 12.1 Scanner rejects negative depth

(or restore the previous 3, matching the EE11 runtime). Either keeps deep WEB-INF rescans working without violating Jetty's walkFileTree contract.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions