Skip to content

Auto-bump spec version to iOS18 for models with no inputs#2684

Open
john-rocky wants to merge 2 commits into
apple:mainfrom
john-rocky:fix-no-input-deployment-target
Open

Auto-bump spec version to iOS18 for models with no inputs#2684
john-rocky wants to merge 2 commits into
apple:mainfrom
john-rocky:fix-no-input-deployment-target

Conversation

@john-rocky
Copy link
Copy Markdown
Contributor

Summary

  • Models that take no inputs require Core ML specification version ≥ 9 (iOS18). Without this fix, ct.convert(...) falls back to the default mlprogram spec version 6 (iOS15) and the resulting mlpackage fails to compile at predict time with:

    Error reading protobuf spec. validator error: Empty input is only valid in specification version >= 9. This model has version 6.

  • After the MIL Program is built, detect that main has no inputs and bump the target spec version up to iOS18 (with a warning). If the user explicitly requested an older target, the existing check_deployment_compatibility step at the entry point surfaces the conflict.

Test plan

  • New test TestTorchExportConversionAPI::test_no_input_model_bumps_spec_version exercises the issue repro and asserts spec.specificationVersion >= ct.target.iOS18.value, then runs verify_prediction(mlmodel).
  • Manually verified surrounding behavior:
    • Model with inputs: spec version stays at 6 (no bump, no warning).
    • Explicit minimum_deployment_target=ct.target.iOS18 with no input: stays at 9, no warning.
    • Explicit minimum_deployment_target=ct.target.iOS15 with no input: bumps + the existing compatibility check raises a clear error.
  • pytest test_torch_export_conversion_api.py -k "image_input or default_io_names or source_dialect_metadata" regression — 3 passed.

Fixes #2578.

Models that take no inputs require Core ML specification version >= 9
(iOS18). Without this fix, `ct.convert(...)` defaults to spec version 6
(iOS15) and the resulting mlpackage fails to compile at predict time
with:

  Error reading protobuf spec. validator error: Empty input is only
  valid in specification version >= 9. This model has version 6.

After the prog is built, detect that `main` has no inputs and bump the
target spec version up to iOS18 (with a warning). If the user
explicitly requested an older target, the existing
`check_deployment_compatibility` step at the entry point surfaces the
conflict.

Fixes apple#2578.
@john-rocky john-rocky force-pushed the fix-no-input-deployment-target branch from 0d97c52 to 8d1a548 Compare May 6, 2026 00:28
and spec_version is not None
and spec_version < _SPECIFICATION_VERSION_IOS_18
):
main_func = prog.functions.get(prog.default_function_name)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In this case I think we should fail, with a clear error message that telling the user they need to change their deployment target.

assert mlmodel.user_defined_metadata[_METADATA_SOURCE_DIALECT] == dialect_name

@pytest.mark.parametrize("frontend", frontends)
def test_no_input_model_bumps_spec_version(self, frontend):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's also check the error case here, see my other comment.

@john-rocky
Copy link
Copy Markdown
Contributor Author

Thanks — agreed, failing with a clear error is the right behavior. Reworked in 4f65a78:

Behavior change (converter.py)

  • No-input + spec version < iOS18 now raises ValueError instead of bumping. Message points the user at the fix:

    Model has no inputs, which requires a deployment target of iOS18 / macOS15 or later (specification version 9); the requested target maps to specification version 6. Re-run ct.convert(...) with minimum_deployment_target=ct.target.iOS18 (or a later target).

  • Dropped the now-unused _logger import.

Test change (test_torch_export_conversion_api.py, renamed test_no_input_model_requires_ios18)

  • Asserts pytest.raises(ValueError, match=r"minimum_deployment_target=ct\.target\.iOS18") for the default target.
  • Then re-runs with minimum_deployment_target=ct.target.iOS18 and verifies spec.specificationVersion >= ct.target.iOS18.value + verify_prediction(mlmodel) for the happy path.

Verified locally on the same toy model (forward(self): return torch.ones(5, 5)): default target raises the new error, iOS18 target converts through MIL cleanly.

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.

coremltools does not correctly infer the minimum_deployment_target for models with no inputs

2 participants