goharbor/harbor · warning
chart name: {} is illegal
Error message
chart name: {} is illegal What it means
Raised inside ChartV2.__init__ when read_chart_version succeeded but the parsed Chart.yaml produced an empty or None name or version. Note the latent bug: the message formats '-'.join(parts) but `parts` is not defined in scope, so what actually raises is a NameError; the surrounding except swallows it, prints 'Skipped chart ... illegal chart name', and the chart is later skipped in the migration loop for having empty name/version.
Source
Thrown at tools/migrate_chart/migrate_chart.py:78
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(
host=hostname,
project=self.project,
name=self.name,
version=self.version),
auth=requests.auth.HTTPBasicAuth(username, password))
def migrate(self, hostname, username, password):
res = self.__check_exist(hostname, username, password)
if res.status_code == 200:
raise Exception("Artifact already exist in harbor")
if res.status_code == 401:
raise Exception(res.reason)View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Open the chart's Chart.yaml and add non-empty `name` and `version` fields
- Validate before placing the tgz in chart storage: helm lint or helm show chart <tgz>
- Fix the format-string bug so the real diagnostics print instead of a NameError
- Re-run the migration; skipped charts stay unmigrated until corrected
Example fix
# before
raise Exception('chart name: {} is illegal'.format('-'.join(parts))) # NameError: 'parts' undefined
# after
raise Exception('chart name/version is illegal: {} (name={!r}, version={!r})'.format(filepath, self.name, self.version)) Defensive patterns
Strategy: validation
Validate before calling
import tarfile, yaml
def chart_metadata_ok(tgz_path) -> bool:
with tarfile.open(tgz_path, 'r:gz') as tar:
for m in tar.getmembers():
if m.isfile() and m.name.endswith('Chart.yaml'):
data = yaml.safe_load(tar.extractfile(m)) or {}
name, version = data.get('name'), data.get('version')
return bool(name) and bool(version) and isinstance(name, str) and isinstance(version, str)
return False Try / catch
try:
chart = ChartV2(path)
except Exception as e:
# ChartV2 already swallows this internally; guard the outer loop anyway
click.echo(f'Skipped chart {path}: {e}', err=True)
continue Prevention
- Run helm lint on charts before packaging
- Assert name and version are non-empty strings in your chart CI template
- Fix the '-'.join(parts) NameError in the tool so real diagnostics are visible
When it happens
Trigger: Chart.yaml parses as YAML but lacks a `name:` or `version:` key, has empty values, or has case typos like `Version:` — read_chart_version returns None/empty for the missing field and this branch fires.
Common situations: Hand-edited Chart.yaml files, template-generated charts where the version was never bumped, apiVersion v2 charts with omitted fields.
Related errors
- Failed to read chart.yaml from the chart tgz file. filename
- chart.yaml not found in the chart tgz file. filename {}
- Artifact already exist in harbor
- This operation only allowed for admin
- BAD_REQUEST
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/ba603193a0349b3e.
Report an issue: GitHub.