You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
GCS skill loaders ignore a skill.md manifest that the local and zip loaders accept #7842
Describe the Bug:
A skill whose manifest is named skill.md loads from a local directory or a zip archive but is invisible when stored in GCS. _parse_skill_md, _list_skills_in_dir and the zip loader in skills/_utils.py all accept SKILL.md or skill.md. _list_skills_in_gcs_dir and _load_skill_from_gcs_dir only look for SKILL.md. Moving a skill that works locally into a bucket therefore makes it disappear from the listing, and loading it raises FileNotFoundError. The async wrappers call the same functions and behave the same way.
Steps to Reproduce:
Upload a skill directory with gs://my-bucket/skills/my-skill/skill.md (valid frontmatter, name: my-skill).
Expected Behavior:
The skill is listed and loads, as it does from a local directory.
Observed Behavior:
The listing is {}, and loading raises FileNotFoundError: SKILL.md not found at gs://my-bucket/skills/my-skill/SKILL.md.
Environment Details:
ADK Library Version (pip show google-adk): 2.13.0 (also on main at 75fb788)
Desktop OS: macOS
Python Version (python -V): 3.11.16
Model Information:
Are you using LiteLLM: No
Which model is being used: N/A (skill loading)
🟡 Optional Information
Additional Context:
I verified this with the mocked google.cloud.storage client the existing GCS skill tests use; I don't have a bucket for a live run.
How often has this issue occurred?:
Always (100%), for GCS skills whose manifest is skill.md
Thanks @adityasingh2400, Reproduced this on 2.13.0 with a mocked storage client: the local loader picks up skill.md but the GCS list comes back empty and the load throws FileNotFoundError.
For now renaming the manifest to SKILL.md in the bucket gets around it. If that’s not an option, wrapping the bucket so it falls back to skill.md when SKILL.md is missing worked for me on both list and load. Could you check if one of these works on your side?
Before #7843 goes for review please give it a good round of testing too, especially that SKILL.md is still tried first and existing skills load the same as before.
Thanks for reproducing it. Renaming to SKILL.md does work around it, but the local and zip loaders already accept skill.md, so #7843 makes the GCS loader match them rather than asking people to rename their buckets.
On ordering: _find_gcs_skill_manifest checks SKILL.md first and only looks up skill.md when it is missing. I just pushed a test for the case where both files exist (test__load_skill_from_gcs_dir_prefers_uppercase_manifest): the loader reads SKILL.md and never looks up skill.md. That test passes on main too, so existing skills load exactly as before. The existing SKILL.md tests pass unmodified, and tests/unittests/skills passes (134 tests).
Activity
surajksharma07 commentedon Oct 30, 2026
Thanks @adityasingh2400, Reproduced this on 2.13.0 with a mocked storage client: the local loader picks up skill.md but the GCS list comes back empty and the load throws FileNotFoundError.
For now renaming the manifest to SKILL.md in the bucket gets around it. If that’s not an option, wrapping the bucket so it falls back to skill.md when SKILL.md is missing worked for me on both list and load. Could you check if one of these works on your side?
Before #7843 goes for review please give it a good round of testing too, especially that SKILL.md is still tried first and existing skills load the same as before.
adityasingh2400 commentedon Oct 31, 2026
Thanks for reproducing it. Renaming to
SKILL.mddoes work around it, but the local and zip loaders already acceptskill.md, so #7843 makes the GCS loader match them rather than asking people to rename their buckets.On ordering:
_find_gcs_skill_manifestchecksSKILL.mdfirst and only looks upskill.mdwhen it is missing. I just pushed a test for the case where both files exist (test__load_skill_from_gcs_dir_prefers_uppercase_manifest): the loader readsSKILL.mdand never looks upskill.md. That test passes onmaintoo, so existing skills load exactly as before. The existingSKILL.mdtests pass unmodified, andtests/unittests/skillspasses (134 tests).