apache/beam · error · ValueError
Unable to parse jar URL "%s". If using a full URL, make sure
Error message
Unable to parse jar URL "%s". If using a full URL, make sure the scheme is specified. If using a local file path, make sure the file exists; you may have to first build the job server using `./gradlew runners:flink:%s:job-server:shadowJar`.
What it means
FlinkUberJarJobServer.executable_jar validates the configured job-server jar: if the path does not exist on disk and is not a URL with a scheme, it raises ValueError. It first attempts flink_version() to interpolate a concrete version into the gradle build hint, falling back to the literal '$FLINK_VERSION' if that probe fails.
Source
Thrown at sdks/python/apache_beam/runners/portability/flink_uber_jar_job_server.py:71
options.view_as(pipeline_options.JobServerOptions).artifact_port)
self._temp_dir = tempfile.mkdtemp(prefix='apache-beam-flink')
def start(self):
return self
def stop(self):
pass
def executable_jar(self):
if self._executable_jar:
if not os.path.exists(self._executable_jar):
parsed = urllib.parse.urlparse(self._executable_jar)
if not parsed.scheme:
try:
flink_version = self.flink_version()
except Exception:
flink_version = '$FLINK_VERSION'
raise ValueError(
'Unable to parse jar URL "%s". If using a full URL, make sure '
'the scheme is specified. If using a local file path, make sure '
'the file exists; you may have to first build the job server '
'using `./gradlew runners:flink:%s:job-server:shadowJar`.' %
(self._executable_jar, flink_version))
url = self._executable_jar
else:
url = job_server.JavaJarJobServer.path_to_beam_jar(
':runners:flink:%s:job-server:shadowJar' % self.flink_version())
return job_server.JavaJarJobServer.local_jar(
url, user_agent=self._user_agent)
def flink_version(self):
full_version = requests.get(
'%s/v1/config' % self._master_url, timeout=60).json()['flink-version']
# Only return up to minor version.
return '.'.join(full_version.split('.')[:2])
View on GitHub (pinned to 12126d8942)
Solutions
- Build the matching jar: `./gradlew runners:flink:<version>:job-server:shadowJar` and point executable_jar at it.
- Supply a full URL with scheme (file:///path or http://...) if the jar lives remotely.
- Check the configured path exists and matches the cluster's Flink version.
Example fix
// before
FlinkUberJarJobServer(master_url=..., executable_jar='/opt/beam/job-server.jar')
// after
FlinkUberJarJobServer(
master_url=...,
executable_jar='file:///opt/beam/beam-runners-flink-1.17-job-server.jar') Defensive patterns
Strategy: validation
Validate before calling
import os
jar = executable_jar
if jar and not os.path.exists(jar) and '://' not in jar:
raise FileNotFoundError(
f"build it: ./gradlew runners:flink:<ver>:job-server:shadowJar ({jar})") Try / catch
try:
server = FlinkUberJarJobServer(master_url=..., executable_jar=jar)
server.create_beam_job(...)
except ValueError as e:
if 'Unable to parse jar URL' in str(e):
build_job_server_jar()
server = FlinkUberJarJobServer(
master_url=..., executable_jar=built_jar_path())
else:
raise Prevention
- Verify the shadowJar exists on the machine launching the job server.
- Match the job-server jar's Flink version to the cluster version.
- Use a file:// or http:// URL if the jar is fetched remotely.
When it happens
Trigger: Constructing/using FlinkUberJarJobServer with an executable_jar that neither exists locally nor has a URL scheme; the '$FLINK_VERSION' placeholder in the message means even the version probe failed (jar absent).
Common situations: Passing --flink_job_server_jar a path where the shadowJar was never built; version mismatch between installed Flink and the built job-server jar; jobservers on machines without gradle builds.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unable to parse jar URL "%s". If using a full URL, make sure
- poll_interval_sec must be >= 15, got {poll_interval_sec}
- buffer_sec must be >= 0, got {buffer_sec}
- max_records_per_bundle must be >= 1, got %r
- max_read_time_seconds must be > 0, got %r
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/edc4f8419ce5cf79.
Report an issue: GitHub.