nodejs/node · error · Exception

{} not in roots {}

Error message

{} not in roots {}

What it means

adb-d8.py runs a tiny TCP file server on the host that pushes requested files to an Android device running d8. As a security boundary it only serves files under one of the configured root_dirs. If the requested filename, made absolute, doesn't start with any allowed root, it raises to refuse serving outside the jail.

Source

Thrown at deps/v8/tools/adb-d8.py:42

import struct
import threading
import subprocess
import SocketServer # TODO(leszeks): python 3 compatibility

def CreateFileHandlerClass(root_dirs, verbose):
  class FileHandler(SocketServer.BaseRequestHandler):
    def handle(self):
      data = self.request.recv(1024);
      while data[-1] != "\0":
        data += self.request.recv(1024);

      filename = data[0:-1]

      try:
        filename = os.path.abspath(filename)

        if not any(filename.startswith(root) for root in root_dirs):
          raise Exception("{} not in roots {}".format(filename, root_dirs))
        if not os.path.isfile(filename):
          raise Exception("{} is not a file".format(filename))

        if verbose:
          sys.stdout.write("Serving {}\r\n".format(os.path.relpath(filename)))

        with open(filename) as f:
          contents = f.read();
          self.request.sendall(struct.pack("!i", len(contents)))
          self.request.sendall(contents)

      except Exception as e:
        if verbose:
          sys.stderr.write(
            "Request failed ({})\n".format(e).replace('\n','\r\n'))
        self.request.sendall(struct.pack("!i", -1))

  return FileHandler

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Start adb-d8.py with a root_dir that contains the file the device is requesting (or its parent).
  2. Make sure root_dirs are specified with a trailing separator so prefix matching is directory-accurate.
  3. On the device side, request paths that are genuinely within the served tree.

Example fix

# before: server rooted at build/, device wants a sibling
python adb-d8.py --port 5039 /home/me/v8/build
# after
python adb-d8.py --port 5039 /home/me/v8
Defensive patterns

Strategy: validation

Validate before calling

import os
requested = os.path.abspath(filename)
roots = [r if r.endswith(os.sep) else r + os.sep for r in root_dirs]
assert any(requested.startswith(r) for r in roots), f'{requested} outside allowed roots {roots}'

Prevention

When it happens

Trigger: Raised in FileHandler.handle() when `not any(os.path.abspath(filename).startswith(root) for root in root_dirs)` is true. The filename comes from the device's raw request bytes (terminated by NUL).

Common situations: The device asks for a source file outside the directory you started the server on (e.g. it wants a system library but you rooted the server at your build out/); path-handling differences where the request uses ../ to escape; root_dirs passed with no trailing slash so prefix matching fails on sibling directories.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/d716d41ae17e97e7. Report an issue: GitHub.