Skip to content

fix(preprocess): report empty metadata.yaml clearly - #2975

Open
abhiramshaji-cyber wants to merge 1 commit into
canonical:mainfrom
abhiramshaji-cyber:issue-2071-empty-metadata-yaml-error
Open

abhiramshaji-cyber wants to merge 1 commit into
canonical:mainfrom
abhiramshaji-cyber:issue-2071-empty-metadata-yaml-error

Conversation

@abhiramshaji-cyber

Copy link
Copy Markdown

Fixes #2071

When metadata.yaml is empty, packing a charm now says the file is empty instead of claiming it breaks the Juju specification.

What this code is for

add_metadata in charmcraft/preprocess.py runs when Charmcraft loads a project, before charmcraft pack and other commands. If a metadata.yaml sits next to charmcraft.yaml, it reads that file with util.safe_yaml_load and copies its fields into the project data.

Before this PR

A charm author has a valid charmcraft.yaml and a leftover metadata.yaml that holds only a license comment, then runs charmcraft pack.

  1. add_metadata finds metadata.yaml and loads it with util.safe_yaml_load.
  2. A file with no content, or only comments, loads as None.
  3. None is not a dict, so the if not isinstance(metadata_yaml, dict) check raises.
  4. The author sees Invalid file: 'metadata.yaml' with Ensure metadata.yaml meets the juju metadata.yaml specification.
  5. The author goes looking for a schema mistake in a file that has nothing in it.

After this PR

Same author, same command.

  1. Same as above through step 2.
  2. A new if metadata_yaml is None check runs first and raises Empty file: 'metadata.yaml'.
  3. The author sees Add the charm metadata to metadata.yaml or delete the file. and knows what to do.
  4. A metadata.yaml that holds a list or a plain string still gets Invalid file: 'metadata.yaml', as before.

The diagram

flowchart LR

classDef box fill:#eef1ff,stroke:#4c5bd4,color:#111827
classDef bad fill:#ffd6d6,stroke:#cc0000,color:#111827,stroke-width:3px
classDef good fill:#c8f0c8,stroke:#008800,color:#111827,stroke-width:3px

subgraph BEFORE["BEFORE: empty file reported as invalid"]
direction TB
  B1["charmcraft pack"] --> B2["add_metadata"]
  B2 --> B3["util.safe_yaml_load returns None"]
  B3 --> B4{"not isinstance dict"}
  B4 -->|"None is not a dict"| B5["Invalid file: 'metadata.yaml'"]
  B4 -->|"mapping"| B6["fields copied into project"]
end

subgraph AFTER["AFTER: empty file reported as empty"]
direction TB
  A1["charmcraft pack"] --> A2["add_metadata"]
  A2 --> A3["util.safe_yaml_load returns None"]
  A3 --> A4{"THE CHANGE: metadata_yaml is None"}
  A4 -->|"empty or only comments"| A5["Empty file: 'metadata.yaml'"]
  A4 -->|"mapping"| A6["fields copied into project"]
end

B1 ~~~ A1

class B1,B2,B3,B6 box
class A1,A2,A3,A6 box
class B4,B5 bad
class A4,A5 good

linkStyle 3 stroke:#cc0000,stroke-width:5px
linkStyle 8 stroke:#008800,stroke-width:5px

style BEFORE fill:#fff5f5,stroke:#cc0000,color:#111827
style AFTER fill:#f3fff3,stroke:#008800,color:#111827
Loading

The change

add_metadata gets an if metadata_yaml is None check before the existing isinstance check. It raises CraftValidationError with the message Empty file: 'metadata.yaml', a resolution telling the author to fill or delete the file, the same docs link, and the same exit code 65. tests/unit/test_preprocess.py now expects the new message for an empty file and a comment only file, and keeps a case for a list that still gets Invalid file. The 4.6 release notes list the fix.

What changes for a user

  • An empty or comment only metadata.yaml now gives a message that names the real problem.
  • A metadata.yaml with the wrong shape still gets Invalid file: 'metadata.yaml'.
  • A valid metadata.yaml is read exactly as before.
  • The exit code stays 65 in both error cases.

  • I've followed the contribution guidelines.
  • I've signed the CLA.
  • I've successfully run make lint && make test.
  • I've added or updated any relevant documentation.
  • In documents I changed, I added a meta description if one was missing.
  • I've updated the relevant release notes.

@abhiramshaji-cyber

Copy link
Copy Markdown
Author

@lengau this picks up #2071, which you had left open for someone in the community to take. It is ready for review whenever you have a slot.

An empty metadata.yaml, or one holding only comments, loads as nothing and
was reported as an invalid file that does not meet the Juju specification.
That message sends people looking for a schema problem when the file has no
content at all. Report it as an empty file and suggest filling or deleting it.

Fixes canonical#2071
@abhiramshaji-cyber
abhiramshaji-cyber force-pushed the issue-2071-empty-metadata-yaml-error branch from e3c6251 to eb7ca82 Compare October 30, 2026 16:15
@abhiramshaji-cyber

Copy link
Copy Markdown
Author

I rebased this onto the latest main. The diff-schema, lint / files and Read the Docs failures all came from the python-apt wheel download returning 403 during setup, and #2976 fixed that on main. I also ran the schema generator, the preprocess unit tests, ruff and the docs build (warnings treated as errors) locally, and they all pass.

The OSV scanner and snap-tests failures look unrelated to this change, since they also fail on main right now, for example https://github.com/canonical/charmcraft/actions/runs/40889779582 (OSV, flagging filelock) and https://github.com/canonical/charmcraft/actions/runs/40889778815 (snap-tests).

If you'd like anything changed in the fix, the test or the release note wording, just let me know.

@abhiramshaji-cyber

Copy link
Copy Markdown
Author

Hi, hope you're doing well! Thanks for your time. When someone has a moment, could the workflow runs be approved? The OSV and snap test failures also happen on main, as noted above, and I'm happy to change anything you'd prefer.

@abhiramshaji-cyber

Copy link
Copy Markdown
Author

Thanks for approving and running CI. I went through each failing job, and as far as I can tell none of them come from this change:

  • snap-tests 20.04: metafiles-bad-yaml-unenforced fails because actions.yaml is missing from the packed charm. That test fails the same way on main: https://github.com/canonical/charmcraft/actions/runs/40889778815/job/123515877954
  • snap-tests 22.04 and 26.04: ssh/read tcp errors and an lxc exec TimeoutExpired in init-extensions. Similar infra failures show up in the same main run.
  • OSV scanner: filelock 4.1.0 and virtualenv 21.14.12, identical to main: https://github.com/canonical/charmcraft/actions/runs/40889779582
  • lint / docs: linkcheck read timeouts on 17 charmhub.io links, with no broken links reported.
  • Slow tests: test_fetchlib_simple_downloaded hit ConnectionResetError from the store. Both of these pass on main, so they look like network flakes and a rerun may clear them.

Happy to change anything if you see it differently.

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.

yaml validation errors are not helpful if the file is empty

1 participant