Summary
chartify crashes with an opaque assertion error when a chart renders zero resources (e.g. all templates gated behind a falsy {{- if .Values.enabled }}). Downstream tools (helmfile) then have to string-match the error text to recover, which is fragile. It would be better for chartify to either handle empty renders gracefully or expose a typed/sentinel error.
Error
assertion failed: unexpected dir entry "" it must be the abs path to the output directory
Root cause
In replace.go, after running helm template --output-dir <dir>, chartify loops over the entries of the output dir expecting exactly one directory (the rendered chart):
// replace.go (current main), roughly lines 133-152
var chartOutputDir string
for _, e := range helmOutputDirEntries {
if !e.IsDir() {
return nil, fmt.Errorf("encountered unexpected dir entry at %s: it must be a dir but was not", e.Name())
}
if chartOutputDir != "" {
return nil, fmt.Errorf("assertion failed: there should be only one dir entry under the helm output dir %s", chartOutputDir)
}
chartOutputDir = filepath.Join(helmOutputDir, e.Name())
}
if !filepath.IsAbs(chartOutputDir) {
return nil, fmt.Errorf("assertion failed: unexpected dir entry %q it must be the abs path to the output directory", chartOutputDir)
}
When the chart renders no resources, helm template --output-dir produces an empty directory, so the for loop body never executes and chartOutputDir stays "". The subsequent !filepath.IsAbs(chartOutputDir) check then fails on the empty string, producing the error above. (That final branch is effectively only reachable via the empty-render case, since chartOutputDir is otherwise filepath.Join(helmOutputDir, e.Name()) with helmOutputDir absolute.)
Reproduction
Any chart whose templates all render to nothing:
# templates/cm.yaml
{{- if .Values.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cm
data:
hello: world
{{- end }}
helm template --output-dir /tmp/out mychart --set enabled=false
ls -A /tmp/out # empty
Combined with chartify (e.g. via helmfile with a transformers/jsonPatches/strategicMergePatches entry, which routes through chartify), this triggers the assertion.
Suggested fix
A couple of options, in order of preference:
- Treat empty render as a no-op success. When
helmOutputDirEntries is empty (and only then), there is nothing for chartify to replace, so return the original chart path as-is rather than erroring. This matches what callers want to do anyway (helmfile currently has to recover into exactly this behavior — see below).
- Expose a typed/sentinel error (e.g.
ErrEmptyRenderOutput) so callers can detect this case without matching on error text.
Either way, the assertion-on-empty-string path is surprising and hard to handle correctly downstream.
Downstream context
This is currently being worked around in helmfile/helmfile#2724 by string-matching it must be the abs path to the output directory. That match is sound today but inherently fragile against future chartify error-wording changes, and a fix here would let helmfile drop the substring match entirely.
Happy to follow up with a PR here if either option above sounds acceptable.
Summary
chartifycrashes with an opaque assertion error when a chart renders zero resources (e.g. all templates gated behind a falsy{{- if .Values.enabled }}). Downstream tools (helmfile) then have to string-match the error text to recover, which is fragile. It would be better for chartify to either handle empty renders gracefully or expose a typed/sentinel error.Error
Root cause
In
replace.go, after runninghelm template --output-dir <dir>, chartify loops over the entries of the output dir expecting exactly one directory (the rendered chart):When the chart renders no resources,
helm template --output-dirproduces an empty directory, so theforloop body never executes andchartOutputDirstays"". The subsequent!filepath.IsAbs(chartOutputDir)check then fails on the empty string, producing the error above. (That final branch is effectively only reachable via the empty-render case, sincechartOutputDiris otherwisefilepath.Join(helmOutputDir, e.Name())withhelmOutputDirabsolute.)Reproduction
Any chart whose templates all render to nothing:
helm template --output-dir /tmp/out mychart --set enabled=false ls -A /tmp/out # emptyCombined with chartify (e.g. via helmfile with a
transformers/jsonPatches/strategicMergePatchesentry, which routes through chartify), this triggers the assertion.Suggested fix
A couple of options, in order of preference:
helmOutputDirEntriesis empty (and only then), there is nothing for chartify to replace, so return the original chart path as-is rather than erroring. This matches what callers want to do anyway (helmfile currently has to recover into exactly this behavior — see below).ErrEmptyRenderOutput) so callers can detect this case without matching on error text.Either way, the assertion-on-empty-string path is surprising and hard to handle correctly downstream.
Downstream context
This is currently being worked around in helmfile/helmfile#2724 by string-matching
it must be the abs path to the output directory. That match is sound today but inherently fragile against future chartify error-wording changes, and a fix here would let helmfile drop the substring match entirely.Happy to follow up with a PR here if either option above sounds acceptable.