{"record":{"id":"24518ae598b2cca6","repo":"goharbor/harbor","slug":"chart-yaml-not-found-in-the-chart-tgz-file-filena","errorCode":null,"errorMessage":"chart.yaml not found in the chart tgz file. filename {}","messagePattern":"chart\\.yaml not found in the chart tgz file\\. filename (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/migrate_chart/migrate_chart.py","lineNumber":66,"sourceCode":"def read_chart_version(chart_tgz_path):\n    # Open the chart tgz file\n    with tarfile.open(chart_tgz_path, 'r:gz') as tar:\n        # Find the path to chart.yaml within the tarball\n        chart_yaml_path = find_chart_yaml(tar)\n        if chart_yaml_path:\n            # Extract the chart.yaml file\n            chart_yaml_file = tar.extractfile(chart_yaml_path)\n            if chart_yaml_file is not None:\n                # Load the YAML content from chart.yaml\n                chart_data = yaml.safe_load(chart_yaml_file)\n                # Read the version from chart.yaml\n                version = chart_data.get('version')\n                name = chart_data.get('name')\n                return name, version\n            else:\n                raise Exception(\"Failed to read chart.yaml from the chart tgz file. filename {}\".format(chart_tgz_path))\n        else:\n            raise Exception(\"chart.yaml not found in the chart tgz file. filename {}\".format(chart_tgz_path))\n\nclass ChartV2:\n\n    def __init__(self, filepath:Path):\n        self.filepath = filepath\n        self.project = self.filepath.parts[-2]\n        self.name = \"\"\n        self.version = \"\"\n        try:\n            self.name, self.version = read_chart_version(filepath)\n            if self.name == \"\" or self.version == \"\" or self.name is None or self.version is None :\n                raise Exception('chart name: {} is illegal'.format('-'.join(parts)))\n        except Exception as e:\n            click.echo(\"Skipped chart: {} due to illegal chart name. Error: {}\".format(filepath, e), err=True)\n        return\n\n    def __check_exist(self, hostname, username, password):\n        return requests.get(CHART_URL_PATTERN.format(","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/tools/migrate_chart/migrate_chart.py#L48-L84","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["List the archive: tar -tzf <file>.tgz and confirm a capitalized Chart.yaml exists at the chart root","If the file is lowercase, rename it to Chart.yaml inside the archive or repackage with helm package","Move non-chart tgz files out of /chart_storage before running the tool","Patch the matcher to compare basename case-insensitively if your charts legitimately use lowercase"],"exampleFix":"# before\nif \"Chart.yaml\" in member.name:  # case-sensitive substring\n    return os.path.join(path, member.name)\n# after\nif member.isfile() and os.path.basename(member.name).lower() == \"chart.yaml\":\n    return member.name","handlingStrategy":"validation","validationCode":"import tarfile\n\ndef contains_chart_yaml(tgz_path) -> bool:\n    with tarfile.open(tgz_path, 'r:gz') as tar:\n        return any('Chart.yaml' in m.name for m in tar.getmembers())\n\n# run before the migration tool over every *.tgz and quarantine failures","typeGuard":null,"tryCatchPattern":"try:\n    name, version = read_chart_version(filepath)\nexcept Exception as e:\n    if 'chart.yaml not found' in str(e):\n        # not a helm chart tgz -> move it out and continue\n        filepath.rename(quarantine_dir / filepath.name)\n    else:\n        raise","preventionTips":["Use capitalized Chart.yaml (Helm convention) so the case-sensitive matcher finds it","Verify each archive with tar -tzf before placing it in /chart_storage","Keep only chart tgz files produced by helm package in the migration source tree"],"tags":["python","helm","chart-migration","tarfile","harbor"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}