Skip to content

fix: normalize blank executable to null when loading legacy job configuration - #306

Merged
ogulcanaydogan merged 2 commits into
jenkinsci:masterfrom
ogulcanaydogan:fix/executable-legacy-config-migration
Aug 18, 2026
Merged

fix: normalize blank executable to null when loading legacy job configuration#306
ogulcanaydogan merged 2 commits into
jenkinsci:masterfrom
ogulcanaydogan:fix/executable-legacy-config-migration

Conversation

@ogulcanaydogan

Copy link
Copy Markdown
Contributor

Fixes #303.

The "Executable" field's f:textbox submits an empty string rather than omitting the element when left blank, so any job config saved through the web UI without filling that field persists <executable></executable> instead of no element at all. ExecRemoteAgent rejects any non-null value that is not a valid ssh-agent(.exe) path, so every build using such a job failed with:

FATAL: [ssh-agent] Unable to start agent
java.lang.IllegalArgumentException: Not an ssh-agent executable path (filename must be ssh-agent(.exe)):

Same root cause pattern as #299/#300: a field introduced after some jobs were last saved deserializes or gets submitted as its "empty" value rather than being genuinely absent, and downstream code was not defensive about that empty value.

Normalizes blank input to null in three places, matching the #300 pattern:

  1. ExecRemoteAgent.toSSHAgentPath - treat a blank string the same as null (runtime net)
  2. SSHAgentBuildWrapper constructor - normalize on every new save going forward
  3. SSHAgentBuildWrapper.readResolve() - migrate already-persisted configs, since XStream sets fields directly and bypasses the constructor

Added SSHAgentBuildWrapperExecutableTest covering: blank/whitespace/null input normalizes to null from the constructor, a legacy XML with <executable></executable> deserializes to null, a legacy XML with no <executable> element at all deserializes to null, a valid non-blank path is retained and trimmed, and an already-clean config survives readResolve() unchanged. Full suite green (50/50).

…guration

Configurations saved through the web UI with a blank Executable
field persist it as an empty string rather than omitting it, since
f:textbox does not submit null for an empty text input. ExecRemoteAgent
rejects any non-null value that is not a valid ssh-agent(.exe) path,
so every build using such a job failed with IllegalArgumentException.

Normalize blank input to null in three places: the ExecRemoteAgent
constructor (runtime net), the SSHAgentBuildWrapper constructor (new
saves), and readResolve() (already-persisted configs, since XStream
sets fields directly and bypasses the constructor).

Signed-off-by: Ogulcan Aydogan <[email protected]>
Confirm the blank-normalization added for jenkinsci#303 does not also affect
a valid, non-blank executable path, and that an already-clean config
survives readResolve() unchanged rather than being rewrapped.

Signed-off-by: Ogulcan Aydogan <[email protected]>
@ogulcanaydogan
ogulcanaydogan requested a review from a team as a code owner August 18, 2026 10:39
@ogulcanaydogan
ogulcanaydogan merged commit 8bbe602 into jenkinsci:master Aug 18, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

417: The new executable property broke freestyle builds

1 participant