Skip to content

feat(x2a): Error handling - error from python log#2585

Open
elai-shalev wants to merge 4 commits intoredhat-developer:mainfrom
elai-shalev:errors-propagate
Open

feat(x2a): Error handling - error from python log#2585
elai-shalev wants to merge 4 commits intoredhat-developer:mainfrom
elai-shalev:errors-propagate

Conversation

@elai-shalev
Copy link
Copy Markdown
Contributor

@elai-shalev elai-shalev commented Mar 22, 2026

related to https://redhat.atlassian.net/browse/FLPATH-3456 and to https://redhat.atlassian.net/browse/FLPATH-3454

relies on x2ansible/x2a-convertor#155

This PR fixes propagation of x2a-convertor errors to the user. Previously, when the convertor failed (e.g., AWS ThrottlingException, access denied), the error message was only visible in the k8s pod log. The user would see a generic "Script failed with exit code 1".

Added a run_x2a() wrapper function in the job script that:

  • Streams output in real-time to k8s logs (preserving existing behavior)
  • Captures the output to extract the convertor's error message on failure
  • Passes the actual error (e.g., Error: AWS Bedrock access denied.) as errorDetails to the backend

All 5 uv run app.py calls (init, analyze, migrate, publish-project, publish-aap) now go through this wrapper. Shell-level errors (git clone failures, missing files) continue using the existing pre-set ERROR_MESSAGE pattern.

@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Propagate x2a-convertor errors to users via wrapper function

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add run_x2a() wrapper function to capture tool output and extract error messages
• Replace manual error handling with wrapper calls in all 5 x2a tool invocations
• Extract actual convertor errors from output and propagate to backend as errorDetails
• Preserve real-time output streaming while capturing for error message extraction
Diagram
flowchart LR
  A["x2a tool execution"] -->|"streams output"| B["tee to file"]
  B -->|"captures output"| C["X2A_OUTPUT variable"]
  C -->|"on failure"| D["Extract Error: message"]
  D -->|"set ERROR_MESSAGE"| E["Backend receives actual error"]
  C -->|"on success"| F["Clear ERROR_MESSAGE"]
Loading

Grey Divider

File Changes

1. workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh Error handling +44/-18

Add error extraction wrapper and apply to all tool calls

• Added run_x2a() function that streams output in real-time via tee while capturing to temporary
 file
• Extracts error messages from x2a-convertor output using grep for "Error: " pattern
• Sets ERROR_MESSAGE variable with extracted error or fallback message on failure
• Replaced 5 manual uv run app.py calls (init, analyze, migrate, publish-project, publish-aap)
 with run_x2a wrapper
• Changed publish-aap to use X2A_OUTPUT variable instead of PUBLISH_OUTPUT for AAP project ID
 parsing

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Mar 22, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Unbounded error message size🐞 Bug ⛯ Reliability
Description
run_x2a captures full tool output into X2A_OUTPUT and can set ERROR_MESSAGE to an unbounded
multi-line tail, which cleanup then forwards as a single --error-message CLI argument. If the
output/error block is large (e.g., Python stack traces), the report step can fail (argument
length/memory), and the backend won’t receive the intended error details.
Code

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[R93-107]

+  X2A_OUTPUT=$(cat "${tmpfile}")
+  rm -f "${tmpfile}"
+
+  if [ ${rc} -ne 0 ]; then
+    # Extract the error block from x2a-convertor output.
+    # The convertor prints: \n\nError: <message>\n (potentially multi-line, always last thing before exit)
+    # Find the last "Error: " line number, then grab everything from there to the end.
+    local error_block=""
+    local last_error_line
+    last_error_line=$(echo "${X2A_OUTPUT}" | grep -n "^Error: " | tail -1 | cut -d: -f1)
+    if [ -n "${last_error_line}" ]; then
+      error_block=$(echo "${X2A_OUTPUT}" | tail -n +"${last_error_line}")
+    fi
+    ERROR_MESSAGE="${error_block:-Unexpected error during ${PHASE} phase. See the job log for details.}"
+    exit ${rc}
Evidence
The script stores the entire command output in a shell variable and, on error, may forward a
multi-line block as ERROR_MESSAGE; report_result then passes that message as a command-line argument
to uv run app.py report. This creates a failure mode where large output prevents reporting from
working at all, undermining the PR’s goal of propagating real error details.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[77-111]
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[14-50]
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[113-153]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`run_x2a` captures the full tool output into `X2A_OUTPUT` and may set `ERROR_MESSAGE` to a large multi-line block, which is later passed to `uv run app.py report` as `--error-message`. This can exceed OS argument limits or create memory pressure, causing the reporting call to fail and preventing error propagation.

### Issue Context
The wrapper is used for all phases. The reporting path builds a command array and appends `--error-message "${message}"`.

### Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[77-111]
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[14-50]
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[113-153]

### Suggested fix approach
- Bound what you store in memory:
 - Replace `X2A_OUTPUT=$(cat "${tmpfile}")` with a capped read (e.g., last 64KB): `X2A_OUTPUT=$(tail -c 65536 "${tmpfile}")`.
 - Also cap `ERROR_MESSAGE` length before exiting (e.g., first 4–8KB) to ensure `--error-message` is always safe.
- Alternatively (even safer), avoid storing full output at all:
 - Keep only the extracted error block (capped) for `ERROR_MESSAGE`.
 - For the publish-aap ID parsing, parse directly from the tmpfile (or from a capped buffer) rather than capturing entire output.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. run_x2a error parsing too narrow📎 Requirement gap ⛯ Reliability
Description
On failure, run_x2a only extracts diagnostics from lines starting with Error: , so meaningful
failures like tracebacks or other non-prefixed errors can still fall back to a generic message. This
can prevent propagating actionable x2a-convertor failure details (including exceptions) to
backend/UI errorDetails as required.
Code

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[R96-106]

+  if [ ${rc} -ne 0 ]; then
+    # Extract the error block from x2a-convertor output.
+    # The convertor prints: \n\nError: <message>\n (potentially multi-line, always last thing before exit)
+    # Find the last "Error: " line number, then grab everything from there to the end.
+    local error_block=""
+    local last_error_line
+    last_error_line=$(echo "${X2A_OUTPUT}" | grep -n "^Error: " | tail -1 | cut -d: -f1)
+    if [ -n "${last_error_line}" ]; then
+      error_block=$(echo "${X2A_OUTPUT}" | tail -n +"${last_error_line}")
+    fi
+    ERROR_MESSAGE="${error_block:-Unexpected error during ${PHASE} phase. See the job log for details.}"
Evidence
The checklist requires propagating meaningful convertor stdout/stderr error text (including
exceptions) into backend-visible errorDetails, not generic messages. The added logic only searches
for the last line matching ^Error:  and otherwise sets ERROR_MESSAGE to a generic fallback,
which can miss other meaningful error formats present in output.

Propagate meaningful x2a-convertor failure output into x2a-backend API errorDetails (avoid generic exit-code-only message)
Capture and report x2a-convertor exceptions (e.g., AWS ThrottlingException) instead of leaving them only in logs
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[96-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`run_x2a()` only extracts failure details from output lines that start with `Error: `. If the convertor emits a traceback, recursion-limit message, or other meaningful stderr/stdout content that does not match `^Error: `, `ERROR_MESSAGE` falls back to a generic message, reducing the quality of backend/UI `errorDetails`.

## Issue Context
Compliance requires propagating meaningful x2a-convertor failure output (including exceptions like AWS ThrottlingException) to backend-visible `errorDetails`, and only falling back to a generic message when no meaningful diagnostics can be extracted.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[96-106]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@rhdh-gh-app
Copy link
Copy Markdown

rhdh-gh-app bot commented Mar 22, 2026

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-x2a-backend workspaces/x2a/plugins/x2a-backend patch v1.1.0

@elai-shalev
Copy link
Copy Markdown
Contributor Author

@eloycoto do you like the approach with the grepping, tailing etc? or should we have a more structured way to propagate the error?

@elai-shalev elai-shalev changed the title Error handling - error from python log feat(x2a): Error handling - error from python log Mar 22, 2026
Comment on lines +96 to +106
if [ ${rc} -ne 0 ]; then
# Extract the error block from x2a-convertor output.
# The convertor prints: \n\nError: <message>\n (potentially multi-line, always last thing before exit)
# Find the last "Error: " line number, then grab everything from there to the end.
local error_block=""
local last_error_line
last_error_line=$(echo "${X2A_OUTPUT}" | grep -n "^Error: " | tail -1 | cut -d: -f1)
if [ -n "${last_error_line}" ]; then
error_block=$(echo "${X2A_OUTPUT}" | tail -n +"${last_error_line}")
fi
ERROR_MESSAGE="${error_block:-Unexpected error during ${PHASE} phase. See the job log for details.}"

This comment was marked as resolved.

Comment on lines +93 to +107
X2A_OUTPUT=$(cat "${tmpfile}")
rm -f "${tmpfile}"

if [ ${rc} -ne 0 ]; then
# Extract the error block from x2a-convertor output.
# The convertor prints: \n\nError: <message>\n (potentially multi-line, always last thing before exit)
# Find the last "Error: " line number, then grab everything from there to the end.
local error_block=""
local last_error_line
last_error_line=$(echo "${X2A_OUTPUT}" | grep -n "^Error: " | tail -1 | cut -d: -f1)
if [ -n "${last_error_line}" ]; then
error_block=$(echo "${X2A_OUTPUT}" | tail -n +"${last_error_line}")
fi
ERROR_MESSAGE="${error_block:-Unexpected error during ${PHASE} phase. See the job log for details.}"
exit ${rc}

This comment was marked as resolved.

@eloycoto
Copy link
Copy Markdown
Contributor

can we have a think more deeply about this?

I do not think that the error here is amazing, and can cause ton of problems. What about if we do something here:

https://github.com/x2ansible/x2a-convertor/blob/8dcad18cc102d2e04e50ccd6bb21c0ab0774479d/app.py#L31-L51

And if there is a problem, we can create some kind of "error-details" file based on a env variable?

We can gather after that the exceptions with proper names, etc.. so there is no weird tail things out there.

@elai-shalev
Copy link
Copy Markdown
Contributor Author

can we have a think more deeply about this?

I do not think that the error here is amazing, and can cause ton of problems. What about if we do something here:

https://github.com/x2ansible/x2a-convertor/blob/8dcad18cc102d2e04e50ccd6bb21c0ab0774479d/app.py#L31-L51

And if there is a problem, we can create some kind of "error-details" file based on a env variable?

We can gather after that the exceptions with proper names, etc.. so there is no weird tail things out there.

Yeah I agree, this approach is also a non optimal workaround. An "error-details" file could work. I'm contemplating if we need to change the way the log is structured on the convertor side as well to fit this.

@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Propagate x2a-convertor errors to users via error file

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add run_x2a() wrapper function for consistent error handling
• Capture x2a-convertor errors from file and propagate to backend
• Replace manual ERROR_MESSAGE management with wrapper calls
• Support real-time log streaming while capturing error details
Diagram
flowchart LR
  A["x2a-convertor execution"] -->|writes error on failure| B["X2A_ERROR_FILE"]
  C["run_x2a wrapper"] -->|executes command| A
  C -->|reads error file| B
  C -->|sets ERROR_MESSAGE| D["Backend error reporting"]
  E["Job phases"] -->|init, analyze, migrate, publish| C
Loading

Grey Divider

File Changes

1. workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh Error handling +41/-16

Implement error file-based error propagation wrapper

• Added X2A_ERROR_FILE environment variable to define error capture location
• Introduced run_x2a() wrapper function that executes commands, captures exit codes, and reads
 error details from file
• Replaced manual ERROR_MESSAGE management in init, analyze, migrate phases with run_x2a calls
• Updated publish-project phase to use run_x2a wrapper
• Modified publish-aap phase with inline error handling to capture errors while preserving output
 parsing logic

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Mar 23, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (2)

Grey Divider


Action required

1. run_x2a fallback lacks exit code 📎 Requirement gap ✧ Quality
Description
When x2a-convertor fails and ${X2A_ERROR_FILE} is missing, the new fallback sets ERROR_MESSAGE
to a generic string instead of the required Script failed with exit code N. This can prevent the
backend from surfacing the mandated fallback errorDetails format.
Code

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[R93-97]

+    if [ -f "${X2A_ERROR_FILE}" ]; then
+      ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
+    else
+      ERROR_MESSAGE="Unexpected error during ${PHASE} phase. See the job log for details."
+    fi
Evidence
PR Compliance ID 1 requires that if no meaningful message can be extracted, errorDetails must fall
back to Script failed with exit code N. The added run_x2a() instead sets ERROR_MESSAGE to
Unexpected error during ${PHASE} phase... when the error file is absent.

x2a-backend errorDetails must include meaningful convertor failure output (not generic exit code)
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[93-97]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`run_x2a()` sets a generic `ERROR_MESSAGE` when `${X2A_ERROR_FILE}` is missing, but compliance requires the fallback to be `Script failed with exit code N`.

## Issue Context
The backend relies on `ERROR_MESSAGE` for `errorDetails`. If no meaningful convertor error can be extracted, the required fallback format includes the exit code.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[93-97]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. publish-aap exits with 1 📎 Requirement gap ✧ Quality
Description
The new publish-aap failure handler always exit 1 and uses a generic fallback message when
${X2A_ERROR_FILE} is missing. This prevents the required Script failed with exit code N fallback
and can hide the true exit code from backend errorDetails.
Code

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[R450-457]

+      --project-id "${PROJECT_DIR}" 2>&1 | tee /dev/stderr) || {
+      if [ -f "${X2A_ERROR_FILE}" ]; then
+        ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
+      else
+        ERROR_MESSAGE="Unexpected error during publish phase (publish-aap). See the job log for details."
+      fi
+      exit 1
+    }
Evidence
PR Compliance ID 1 requires a fallback message that includes the actual exit code when no meaningful
message can be extracted. The added block hardcodes exit 1 and sets a generic ERROR_MESSAGE when
the error file is absent, which cannot produce Script failed with exit code N for the real failure
code.

x2a-backend errorDetails must include meaningful convertor failure output (not generic exit code)
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[450-457]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `publish-aap` command failure handler currently hardcodes `exit 1` and uses a generic fallback message when `${X2A_ERROR_FILE}` is missing. Compliance requires `Script failed with exit code N` using the actual command exit code.

## Issue Context
If the convertor doesn't write `${X2A_ERROR_FILE}`, the backend should still receive an actionable fallback that includes the real non-zero exit code.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[450-457]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Error-file read can abort 🐞 Bug ⛯ Reliability
Description
run_x2a and the publish-aap failure handler read ${X2A_ERROR_FILE} via cat while set -e is
in effect, so if the file exists but becomes unreadable/vanishes between the -f check and the
read, the script exits during cat before setting a fallback ERROR_MESSAGE. That defeats the PR’s
goal because the cleanup/report path will then fall back to a generic “Script failed…” message
instead of the real errorDetails.
Code

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[R93-96]

+    if [ -f "${X2A_ERROR_FILE}" ]; then
+      ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
+    else
+      ERROR_MESSAGE="Unexpected error during ${PHASE} phase. See the job log for details."
Evidence
run_x2a re-enables set -e before checking rc and reading the file; the cat is unguarded inside
command substitution, which is subject to set -e termination if it fails. The publish-aap handler
repeats the same unguarded pattern, so both paths can still fail to populate ERROR_MESSAGE.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[84-102]
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[446-457]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`cat "${X2A_ERROR_FILE}"` can fail under `set -e` after a successful `-f` test (TOCTOU), causing an early exit before setting `ERROR_MESSAGE`.

### Issue Context
This occurs in both `run_x2a` and the publish-aap `|| { ... }` handler.

### Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[93-96]
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[450-457]

### Suggested approach
- Read defensively, e.g.:
 - `ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}" 2>/dev/null) || ERROR_MESSAGE="Unexpected error ..."`
 - Or temporarily `set +e` around the `cat` and check its rc.
- Consider trimming to a safe size and removing trailing newlines (optional).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Shared /tmp error file 🐞 Bug ⛯ Reliability
Description
Using a fixed exported path (/tmp/x2a-error.txt) for error details risks collisions with other
processes in the same container namespace and makes error propagation dependent on /tmp
filesystem/permission state. Even though you rm -f before use, a job-specific unique path reduces
the chance of incorrect/missing errorDetails.
Code

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[R14-16]

+# Path where x2a-convertor writes error details on failure
+export X2A_ERROR_FILE="/tmp/x2a-error.txt"
+
Evidence
The script exports a constant path for ${X2A_ERROR_FILE} and later reads it verbatim into
ERROR_MESSAGE; this couples correctness to an external shared location rather than a per-job
unique file.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[14-16]
workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[84-96]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
A constant `/tmp/x2a-error.txt` can collide or be affected by `/tmp` state.

### Issue Context
The file is used to propagate convertor errors into `ERROR_MESSAGE`.

### Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[14-16]

### Suggested approach
- Use a job-unique path, e.g.:
 - `export X2A_ERROR_FILE="/tmp/x2a-error.${JOB_ID}.txt"`
 - or `mktemp -p /tmp "x2a-error.${JOB_ID}.XXXXXX"`
- Optionally delete it in cleanup to reduce leftover state.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +93 to +97
if [ -f "${X2A_ERROR_FILE}" ]; then
ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
else
ERROR_MESSAGE="Unexpected error during ${PHASE} phase. See the job log for details."
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. run_x2a fallback lacks exit code 📎 Requirement gap ✧ Quality

When x2a-convertor fails and ${X2A_ERROR_FILE} is missing, the new fallback sets ERROR_MESSAGE
to a generic string instead of the required Script failed with exit code N. This can prevent the
backend from surfacing the mandated fallback errorDetails format.
Agent Prompt
## Issue description
`run_x2a()` sets a generic `ERROR_MESSAGE` when `${X2A_ERROR_FILE}` is missing, but compliance requires the fallback to be `Script failed with exit code N`.

## Issue Context
The backend relies on `ERROR_MESSAGE` for `errorDetails`. If no meaningful convertor error can be extracted, the required fallback format includes the exit code.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[93-97]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +450 to +457
--project-id "${PROJECT_DIR}" 2>&1 | tee /dev/stderr) || {
if [ -f "${X2A_ERROR_FILE}" ]; then
ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
else
ERROR_MESSAGE="Unexpected error during publish phase (publish-aap). See the job log for details."
fi
exit 1
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. publish-aap exits with 1 📎 Requirement gap ✧ Quality

The new publish-aap failure handler always exit 1 and uses a generic fallback message when
${X2A_ERROR_FILE} is missing. This prevents the required Script failed with exit code N fallback
and can hide the true exit code from backend errorDetails.
Agent Prompt
## Issue description
The `publish-aap` command failure handler currently hardcodes `exit 1` and uses a generic fallback message when `${X2A_ERROR_FILE}` is missing. Compliance requires `Script failed with exit code N` using the actual command exit code.

## Issue Context
If the convertor doesn't write `${X2A_ERROR_FILE}`, the backend should still receive an actionable fallback that includes the real non-zero exit code.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[450-457]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +93 to +96
if [ -f "${X2A_ERROR_FILE}" ]; then
ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
else
ERROR_MESSAGE="Unexpected error during ${PHASE} phase. See the job log for details."
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Error-file read can abort 🐞 Bug ⛯ Reliability

run_x2a and the publish-aap failure handler read ${X2A_ERROR_FILE} via cat while set -e is
in effect, so if the file exists but becomes unreadable/vanishes between the -f check and the
read, the script exits during cat before setting a fallback ERROR_MESSAGE. That defeats the PR’s
goal because the cleanup/report path will then fall back to a generic “Script failed…” message
instead of the real errorDetails.
Agent Prompt
### Issue description
`cat "${X2A_ERROR_FILE}"` can fail under `set -e` after a successful `-f` test (TOCTOU), causing an early exit before setting `ERROR_MESSAGE`.

### Issue Context
This occurs in both `run_x2a` and the publish-aap `|| { ... }` handler.

### Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[93-96]
- workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh[450-457]

### Suggested approach
- Read defensively, e.g.:
  - `ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}" 2>/dev/null) || ERROR_MESSAGE="Unexpected error ..."`
  - Or temporarily `set +e` around the `cat` and check its rc.
- Consider trimming to a safe size and removing trailing newlines (optional).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@mareklibra
Copy link
Copy Markdown
Member

Providing sort of "keys" to the UI will help with translations.

if [ ${rc} -ne 0 ]; then
if [ -f "${X2A_ERROR_FILE}" ]; then
ERROR_MESSAGE=$(cat "${X2A_ERROR_FILE}")
else
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You added the error_message at the end, to be honest, I'll use this as the defult, and if there is ERROR_MESSAGE I'll append to the error message, it'll make more sense to the user.

ERROR_MESSAGE="Unexpected error during ${PHASE} phase. See the job log for more details."
if [ -f "${X2A_ERROR_FILE}" ]; then
ERROR_MESSAGE+="MESSAGE: $cat"
fi

# On failure, reads the error details file written by x2a-convertor and sets ERROR_MESSAGE.
# On success, clears ERROR_MESSAGE.
# Usage: run_x2a uv run app.py <phase> [args...]
run_x2a() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now that we have this fucntion, what about if we add the log here:

echo "Command: uv run app.py init --source-dir ${SOURCE_BASE} \"${USER_REQ}\""

because it's already in all phases, and can be log here without issues, no?

--project-id "${PROJECT_DIR}" 2>&1 | tee /dev/stderr)
ERROR_MESSAGE=""
--project-id "${PROJECT_DIR}" 2>&1 | tee /dev/stderr) || {
if [ -f "${X2A_ERROR_FILE}" ]; then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this is different? You can use the same function as previous, no?

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Member

@mareklibra mareklibra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error messages will be hard to internationalize but otherwise LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants