Skip to content

Escalate XPK clean-up failure to infrastructure team - #4869

Open
olufiyin19 wants to merge 1 commit into
mainfrom
fix-validation-pipeline-qwen3-8b-dag_verify_forward_pass-manual__2026-08-13T05-18-29-739391-00-00-maxtext_golden_
Open

Escalate XPK clean-up failure to infrastructure team#4869
olufiyin19 wants to merge 1 commit into
mainfrom
fix-validation-pipeline-qwen3-8b-dag_verify_forward_pass-manual__2026-08-13T05-18-29-739391-00-00-maxtext_golden_

Conversation

@olufiyin19

Copy link
Copy Markdown
Collaborator

Escalate XPK clean-up failure to infrastructure team

@google-cla

google-cla Bot commented Aug 13, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@olufiyin19
olufiyin19 force-pushed the fix-validation-pipeline-qwen3-8b-dag_verify_forward_pass-manual__2026-08-13T05-18-29-739391-00-00-maxtext_golden_ branch from 2de93d6 to 3025f07 Compare August 13, 2026 05:28

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the "Overwatch" automated model onboarding and verification pipeline for MaxText, which automates checkpoint validation, includes a Cloud Run sidecar agent driven by Gemini for auto-remediation, and adds a comprehensive training engine parity verification suite. The review feedback focuses on enhancing the robustness, performance, and style of the newly added scripts. Key recommendations include adding repository cloning fallbacks in the PR tool, enforcing timeouts on network requests, implementing strict type checks on parsed JSON configurations to prevent runtime crashes, logging caught exceptions during polling, limiting GCS blob listings to avoid performance degradation, avoiding fragile runtime source code modifications, and resolving a PEP 8 naming convention violation.

Comment on lines +36 to +40

repo_dir = "/tmp/maxtext_repo"
fork_branch = args.fix_branch or f"fix/agent-remediation-{int(time.time())}"

print(f"1. Checking out fix branch '{fork_branch}'...")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

If /tmp/maxtext_repo does not exist (e.g., if this tool is executed first or the directory was cleaned up), subprocess.run with cwd=repo_dir will raise a FileNotFoundError and crash. Clone the repository if it does not exist to ensure robustness.

Suggested change
repo_dir = "/tmp/maxtext_repo"
fork_branch = args.fix_branch or f"fix/agent-remediation-{int(time.time())}"
print(f"1. Checking out fix branch '{fork_branch}'...")
repo_dir = "/tmp/maxtext_repo"
fork_branch = args.fix_branch or f"fix/agent-remediation-{int(time.time())}"
if not os.path.exists(repo_dir):
print(f"Cloning repository into {repo_dir}...")
subprocess.run(
["git", "clone", "https://github.com/AI-Hypercomputer/maxtext.git", repo_dir], check=True
)
print(f"1. Checking out fix branch '{fork_branch}'...")
subprocess.run(["git", "checkout", fork_branch], cwd=repo_dir, check=False)


try:
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
with urllib.request.urlopen(req) as response:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The urllib.request.urlopen function is called without a timeout. If the remote server hangs or takes too long to respond, this call will block indefinitely, which can stall the entire agent execution. It is highly recommended to specify a timeout.

Suggested change
with urllib.request.urlopen(req) as response:
with urllib.request.urlopen(req, timeout=30) as response:

Comment on lines +370 to +371
plan_json = json.loads(raw_text.strip())
logger.info(f"Analyst diagnosis: {plan_json.get('diagnosis')}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If the LLM response is not a JSON object (e.g., if it returns a list or a string), calling .get() on plan_json will raise an AttributeError and crash the agent. Adding a type check ensures robust error handling.

    parsed = json.loads(raw_text.strip())
    if not isinstance(parsed, dict):
      raise ValueError("Analyst response is not a JSON object")
    plan_json = parsed
    logger.info(f"Analyst diagnosis: {plan_json.get('diagnosis')}")

Comment on lines +46 to +53
clean_conf = original_conf.get("dag_conf", original_conf)

# Just in case we are dealing with an already nested config from before this fix,
# gracefully un-nest it.
while "dag_conf" in clean_conf:
clean_conf = clean_conf["dag_conf"]

conf_dict.update(clean_conf)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If original_conf is not a dictionary (e.g., if json.loads returned a list or string), calling .get() will raise an AttributeError. Similarly, if clean_conf is not a dictionary, "dag_conf" in clean_conf can raise a TypeError. Adding type checks prevents runtime crashes.

Suggested change
clean_conf = original_conf.get("dag_conf", original_conf)
# Just in case we are dealing with an already nested config from before this fix,
# gracefully un-nest it.
while "dag_conf" in clean_conf:
clean_conf = clean_conf["dag_conf"]
conf_dict.update(clean_conf)
if isinstance(original_conf, dict):
clean_conf = original_conf.get("dag_conf", original_conf)
# Just in case we are dealing with an already nested config from before this fix,
# gracefully un-nest it.
while isinstance(clean_conf, dict) and "dag_conf" in clean_conf:
clean_conf = clean_conf["dag_conf"]
if isinstance(clean_conf, dict):
conf_dict.update(clean_conf)

Comment on lines +58 to +60
except (requests.RequestException, Exception) as e:
# Log warning but don't fail, allowing subsequent poll iterations to retry
pass

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Silently catching and passing on all exceptions (including Exception) is dangerous because it can mask critical bugs (like NameError or TypeError) and cause the loop to run unnecessarily until the 2-hour timeout. Print the warning to sys.stderr so that failures are visible in the logs.

Suggested change
except (requests.RequestException, Exception) as e:
# Log warning but don't fail, allowing subsequent poll iterations to retry
pass
except (requests.RequestException, Exception) as e:
# Log warning but don't fail, allowing subsequent poll iterations to retry
print(f"Warning: encountered exception during poll: {e}", file=sys.stderr)

Comment on lines +322 to +324
for logger_name in [None, "absl"]:
l = logging.getLogger(logger_name)
for h in l.handlers:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

PEP 8 style guide violation. Never use the character 'l' (lowercase letter el) as a single-character variable name because it is indistinguishable from the numeral one ('1') or uppercase letter 'I' in many fonts.

Suggested change
for logger_name in [None, "absl"]:
l = logging.getLogger(logger_name)
for h in l.handlers:
for logger_name in [None, "absl"]:
log_obj = logging.getLogger(logger_name)
for h in log_obj.handlers:
References
  1. PEP 8: Never use the characters 'l' (lowercase letter el), 'O' (uppercase letter oh), or 'I' (uppercase letter eye) as single character variable names. (link)

# applying a monkeypatch to maxtext's model_creation_utils because it has a bug where
# it cannot resolve SequenceKey (list indices) to string keys in Linen checkpoints.

source = inspect.getsource(model_creation_utils._fix_restore_args_for_shape_mismatch) # pylint: disable=protected-access

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Relying on inspect.getsource to dynamically retrieve, regex-replace, and exec library code at runtime is highly fragile. If the source code is not available on disk (e.g., zipped/compiled environments), it will raise an OSError. Furthermore, any minor upstream change to _fix_restore_args_for_shape_mismatch will break the regex replacement and crash the validation pipeline. Consider defining a complete custom version of _fix_restore_args_for_shape_mismatch or refactoring the monkeypatch to avoid string manipulation of the library's source code.

try:
client = storage.Client()
bucket = client.bucket(GCS_BUCKET_NAME)
blobs = list(bucket.list_blobs())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Listing all blobs in the bucket without any limit or prefix can cause severe performance degradation and high memory usage as the bucket grows over time. Consider using max_results or page through the blobs to limit the search space.

Suggested change
blobs = list(bucket.list_blobs())
blobs = list(bucket.list_blobs(max_results=1000))

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.

1 participant