apache/beam · error

error in creating relative path

Error message

error in creating relative path: %w

What it means

After collecting cached classpath JARs, MakeJar computes each jar's path relative to the jar cache directory via filepath.Rel(cacheDir, path); this fails only when the two paths cannot be made relative (e.g. different roots, or the jar sits outside the cacheDir). The wrapped error aborts JAR repackaging because the Class-Path manifest entries must be relative.

Solutions

  1. Ensure $HOME is set and consistent for the process so cacheDir matches where getLocalJar caches jars.
  2. Keep the jar cache and all classpath jars on the same filesystem root/drive.
  3. Check for symlinks resolving classpath jars outside the cache dir; resolve or relocate them.
  4. If HOME cannot be fixed, pre-cache jars under the exact cacheDir MakeJar will compute.

Example fix

// before: HOME unset in service environment
ExecStart=/opt/worker/worker
// after: pin HOME so cacheDir is deterministic
Environment=HOME=/home/beam
ExecStart=/opt/worker/worker
Defensive patterns

Strategy: validation

Validate before calling

cacheDir := filepath.Join(usr.HomeDir, jarCache[2:])
if usr.HomeDir == "" { return errors.New("HOME is unset; cannot compute jar cache dir") }
for _, p := range classpathJars {
    if _, err := filepath.Rel(cacheDir, p); err != nil {
        return fmt.Errorf("jar %s outside cache dir %s", p, cacheDir)
    }
}

Try / catch

relPath, err := filepath.Rel(cacheDir, path)
if err != nil {
    return "", fmt.Errorf("error in creating relative path: %w", err)
}

Prevention

When it happens

Trigger: filepath.Rel(cacheDir, path) returns an error, classically 'Rel: can't make X relative to Y' when a getLocalJar result lives on a different mount/root than cacheDir ($HOME/.beam661bea09-...), or cacheDir couldn't be derived correctly from user.HomeDir (empty HOME).

Common situations: HOME unset or overridden so cacheDir is computed differently from where jars were actually cached; jars placed on a different drive/root than the cache dir; cross-volume symlinks resolving outside the cache.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/55cba60817a1a870. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/xlangx/expansionx/download.go:277

	// fetch jars required in classpath
	classpaths := strings.Split(classpath, " ")
	classpathJars := []string{}
	for _, jar := range classpaths {
		path := expandJar(jar)
		if j, err := getLocalJar(path); err == nil {
			classpathJars = append(classpathJars, j)
		} else {
			return "", fmt.Errorf("error in getLocal(): %w", err)
		}
	}

	// classpath jars should have relative path
	relClasspath := []string{}
	for _, path := range classpathJars {
		relPath, err := filepath.Rel(cacheDir, path)
		if err != nil {
			return "", fmt.Errorf("error in creating relative path: %w", err)
		}
		relClasspath = append(relClasspath, relPath)
	}

	tmpDir := filepath.Join(cacheDir, "tmpDir")

	if err := extractJar(mainJar, tmpDir); err != nil {
		return "", fmt.Errorf("error in extractJar(): %w", err)
	}

	manifest, err := os.ReadFile(tmpDir + "/META-INF/MANIFEST.MF")
	if err != nil {
		return "", fmt.Errorf("error readingf: %w", err)
	}

	// trim the empty lines present at the end of MANIFEST.MF file.
	manifestLines := strings.Split(string(manifest), "\n")
	manifestLines = manifestLines[:len(manifestLines)-2]

View on GitHub (pinned to 12126d8942)