Skip to content

fix(util): import MetaflowInternalError in read_artifacts_module - #3365

Open
Anai-Guo wants to merge 1 commit into
Netflix:masterfrom
Anai-Guo:fix/read-artifacts-module-missing-exception-import
Open

fix(util): import MetaflowInternalError in read_artifacts_module#3365
Anai-Guo wants to merge 1 commit into
Netflix:masterfrom
Anai-Guo:fix/read-artifacts-module-missing-exception-import

Conversation

@Anai-Guo

@Anai-Guo Anai-Guo commented Sep 6, 2026

Copy link
Copy Markdown

Problem

metaflow/util.py::read_artifacts_module raises MetaflowInternalError on both of its error paths, and documents it in the docstring:

Raises
-------
MetaflowInternalError
    If the file cannot be read or does not contain the ARTIFACTS variable.

but the name is never imported into metaflow/util.py. So neither raise can construct the exception — the name lookup fails first and the caller gets:

NameError: name 'MetaflowInternalError' is not defined

pyflakes metaflow/util.py flags exactly these two lines (621, 626) as undefined names.

The function is reachable from the CLI: metaflow/cli_components/step_cmd.py imports it and spin_step calls it whenever --artifacts-module is passed:

spin_artifacts = read_artifacts_module(artifacts_module) if artifacts_module else {}

so a mistyped path, or a module without an ARTIFACTS variable, produces a NameError instead of the intended error.

Fix

Add the deferred import, matching the existing idiom in this same file — compress_list (line 352) does exactly this, function-locally, because metaflow.util is imported early and a module-level from metaflow.exception import ... would risk a circular import:

def compress_list(lst, ...):
    from metaflow.exception import MetaflowInternalError

2 lines added, nothing else touched.

Verification

Real upstream metaflow/util.py and metaflow/exception.py, loaded under a metaflow package namespace with only metaflow._vendor.packaging.version (the single module-level metaflow import in util.py) and metaflow.extension_support (exception.py's extension hook, off the path under test) stubbed:

case before after
path that does not exist NameError: name 'MetaflowInternalError' is not defined MetaflowInternalError: Error reading file ...
module without ARTIFACTS NameError: name 'MetaflowInternalError' is not defined MetaflowInternalError: Error reading file ...
module with ARTIFACTS = {'a': 1} {'a': 1} {'a': 1} (unchanged)

pyflakes metaflow/util.py after the change: no undefined names.

Note (not changed here)

The explicit raise MetaflowInternalError("Module ... does not contain ARTIFACTS variable") inside the try is caught by the function's own broad except Exception as e and re-wrapped as "Error reading file ...", so that more specific message never reaches the user. That is pre-existing and independent of this fix; happy to add an except MetaflowInternalError: raise passthrough in a follow-up if you'd like it preserved.

🤖 Generated with Claude Code

`read_artifacts_module` raises `MetaflowInternalError` on both of its error
paths, but never imports it, so every failure surfaces as
`NameError: name 'MetaflowInternalError' is not defined` instead. The
function is reached from `spin-step --artifacts-module`, so a bad path or a
module without an `ARTIFACTS` variable hits it.

Add the deferred import, matching `compress_list` in the same file (the
import is function-local there to avoid a circular import with
metaflow.exception).
@greptile-apps

greptile-apps Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes read_artifacts_module so its existing error paths can raise the documented MetaflowInternalError instead of failing with an undefined-name error.

  • Adds the exception import locally to avoid the package's circular module dependency.
  • Preserves successful artifact-module loading behavior.
  • Allows CLI-level MetaflowException handling to process invalid artifact modules as intended.

Confidence Score: 5/5

The PR appears safe to merge and correctly restores the intended exception behavior.

The new function-local import follows established patterns in the same module, avoids introducing a module-level circular dependency, and makes both existing error paths raise the documented exception type.

Important Files Changed

Filename Overview
metaflow/util.py Adds the missing deferred import required by both existing MetaflowInternalError raise paths.

Reviews (1): Last reviewed commit: "fix(util): import MetaflowInternalError ..." | Re-trigger Greptile

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