Skip to content

Fix confusing error UX when model serve has missing deps#965

Closed
alfredoclarifai wants to merge 1 commit intocli-improvementfrom
cli-improvement-serve-error-ux
Closed

Fix confusing error UX when model serve has missing deps#965
alfredoclarifai wants to merge 1 commit intocli-improvementfrom
cli-improvement-serve-error-ux

Conversation

@alfredoclarifai
Copy link
Contributor

Summary

  • Fix NoneType crash in check_requirements_installed when model_path is None — was causing a traceback instead of a clean error message
  • Show package names in missing deps list (was only showing version specifiers like >=2.6.0)
  • Show relative path in pip install -r hint instead of absolute
  • Replace UserError traceback with clean click.Abort() since error details are already logged
  • Add tip about --mode env / --mode container alternatives
  • Print playground/API URLs via click.echo() for cleaner terminal output

Test plan

  • Run clarifai model serve . in a directory with missing deps and verify clean error output (no traceback)
  • Verify package names show in the missing deps list
  • Verify pip install -r shows relative path
  • Run clarifai model serve . with all deps installed and verify playground URL prints cleanly

🤖 Generated with Claude Code

- Fix NoneType crash in check_requirements_installed when model_path is None
- Show package names in missing deps list (was only showing version specifiers)
- Show relative path in pip install hint instead of absolute
- Replace UserError traceback with clean click.Abort() since error details are already logged
- Add tip about --mode env/container alternatives
- Print playground/API URLs via click.echo for cleaner terminal output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves the clarifai model serve missing-dependency user experience by making dependency checks more informative (showing package names, better install hints) and by reducing traceback-heavy failures during local serving.

Changes:

  • Enhance missing-deps reporting in check_requirements_installed() (include package names; show relative requirements.txt path when possible; add mode tips).
  • Pass model_path into check_requirements_installed() from model serving flows and switch one failure path to click.Abort().
  • Add additional CLI output logic intended to print Playground/API URLs via click.echo().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
clarifai/utils/cli.py Improves missing dependency list formatting and install guidance output.
clarifai/cli/model.py Updates local serve flows to use improved requirements checking and adjusts abort/error handling and output.

Comment on lines 595 to 601
if not dependencies:
dependencies = parse_requirements(model_path)
missing = [
full_req
f"{package_name}{full_req}" if full_req else package_name
for package_name, full_req in dependencies.items()
if not _is_package_installed(package_name)
]
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

check_requirements_installed() assumes dependencies is a dict and unconditionally iterates dependencies.items(), but parse_requirements() returns [] when requirements.txt is missing. In that case this code raises (list has no items) and falls into the generic exception path, turning a missing requirements.txt into a failed requirements check. Consider returning {} from parse_requirements() (or handling non-dict/empty dependencies here) so “no requirements.txt” is treated predictably (e.g., as no deps) and produces a clean message.

Copilot uses AI. Check for mistakes.
if mode not in ("container", "env"):
dependencies = parse_requirements(model_path)
if not check_requirements_installed(dependencies=dependencies):
if not check_requirements_installed(model_path=model_path, dependencies=dependencies):
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

This call passes both model_path and dependencies. In check_requirements_installed() that combination triggers a warning and re-parses requirements from disk, making the pre-parsed dependencies redundant and adding noisy output. Pass only model_path (letting the helper parse) or adjust check_requirements_installed() to accept both without warning/extra parsing.

Suggested change
if not check_requirements_installed(model_path=model_path, dependencies=dependencies):
if not check_requirements_installed(model_path=model_path):

Copilot uses AI. Check for mistakes.
if mode not in ("container", "env"):
if not check_requirements_installed(dependencies=dependencies):
raise UserError(f"Requirements not installed for model at {model_path}.")
if not check_requirements_installed(model_path=model_path, dependencies=dependencies):
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

Same issue here: passing both model_path and dependencies will cause check_requirements_installed() to warn and re-parse requirements, which undermines the “clean error UX” goal. Prefer calling it with only model_path (or update the helper’s argument-handling logic).

Suggested change
if not check_requirements_installed(model_path=model_path, dependencies=dependencies):
if not check_requirements_installed(model_path=model_path):

Copilot uses AI. Check for mistakes.
Comment on lines +1554 to +1560
def print_code_snippet():
if ctx.obj.current is None:
logger.debug("Context is None. Skipping code snippet generation.")
else:
from clarifai.runners.utils import code_script

snippet = code_script.generate_client_script(
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

print_code_snippet() is defined but never called, so the new click.echo() URL output won’t actually take effect and the extra code becomes dead/maintenance burden. Either call this function (and ensure it uses the local user_id/app_id/model_id/version_id values rather than ctx.obj.current.model_id/model_version_id, which aren’t set here) or remove it and keep the existing snippet/Next Steps output below.

Copilot uses AI. Check for mistakes.
@luv-bansal
Copy link
Contributor

@alfredoclarifai I have included these improvements in my branch, so closing this PR

@luv-bansal luv-bansal closed this Mar 1, 2026
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