goharbor/harbor · error

chart.yaml not found in the chart tgz file. filename {}

Error message

chart.yaml not found in the chart tgz file. filename {}

What it means

Raised by read_chart_version when find_chart_yaml iterated all members of the chart tgz and none contained "Chart.yaml" in its name. The check is a case-sensitive substring match on member.name, so an archive with a lowercase chart.yaml or without chart metadata at all yields no match. The exception is caught in ChartV2.__init__, logged as 'Skipped chart ... illegal chart name', and the chart is skipped.

Source

Thrown at tools/migrate_chart/migrate_chart.py:66

def read_chart_version(chart_tgz_path):
    # Open the chart tgz file
    with tarfile.open(chart_tgz_path, 'r:gz') as tar:
        # Find the path to chart.yaml within the tarball
        chart_yaml_path = find_chart_yaml(tar)
        if chart_yaml_path:
            # Extract the chart.yaml file
            chart_yaml_file = tar.extractfile(chart_yaml_path)
            if chart_yaml_file is not None:
                # Load the YAML content from chart.yaml
                chart_data = yaml.safe_load(chart_yaml_file)
                # Read the version from chart.yaml
                version = chart_data.get('version')
                name = chart_data.get('name')
                return name, version
            else:
                raise Exception("Failed to read chart.yaml from the chart tgz file. filename {}".format(chart_tgz_path))
        else:
            raise Exception("chart.yaml not found in the chart tgz file. filename {}".format(chart_tgz_path))

class ChartV2:

    def __init__(self, filepath:Path):
        self.filepath = filepath
        self.project = self.filepath.parts[-2]
        self.name = ""
        self.version = ""
        try:
            self.name, self.version = read_chart_version(filepath)
            if self.name == "" or self.version == "" or self.name is None or self.version is None :
                raise Exception('chart name: {} is illegal'.format('-'.join(parts)))
        except Exception as e:
            click.echo("Skipped chart: {} due to illegal chart name. Error: {}".format(filepath, e), err=True)
        return

    def __check_exist(self, hostname, username, password):
        return requests.get(CHART_URL_PATTERN.format(

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. List the archive: tar -tzf <file>.tgz and confirm a capitalized Chart.yaml exists at the chart root
  2. If the file is lowercase, rename it to Chart.yaml inside the archive or repackage with helm package
  3. Move non-chart tgz files out of /chart_storage before running the tool
  4. Patch the matcher to compare basename case-insensitively if your charts legitimately use lowercase

Example fix

# before
if "Chart.yaml" in member.name:  # case-sensitive substring
    return os.path.join(path, member.name)
# after
if member.isfile() and os.path.basename(member.name).lower() == "chart.yaml":
    return member.name
Defensive patterns

Strategy: validation

Validate before calling

import tarfile

def contains_chart_yaml(tgz_path) -> bool:
    with tarfile.open(tgz_path, 'r:gz') as tar:
        return any('Chart.yaml' in m.name for m in tar.getmembers())

# run before the migration tool over every *.tgz and quarantine failures

Try / catch

try:
    name, version = read_chart_version(filepath)
except Exception as e:
    if 'chart.yaml not found' in str(e):
        # not a helm chart tgz -> move it out and continue
        filepath.rename(quarantine_dir / filepath.name)
    else:
        raise

Prevention

When it happens

Trigger: A .tgz placed in /chart_storage/<project>/ that is not a Helm chart (random tarball), a chart packed with lowercase chart.yaml (case-sensitive check misses it), or a chart missing its metadata file entirely.

Common situations: Non-chart tgz files dropped into chart storage, tools that emit lowercase chart.yaml, partially uploaded or corrupted archives that still open as gzipped tar.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/24518ae598b2cca6. Report an issue: GitHub.