What happened?
crossplane project run --init-resources <file> (and --extra-resources) fails with:
encountered an invalid or empty raw resource
whenever the manifest begins with a comment block before the first --- document separator — i.e. a file-level header comment, which is a very common convention. kubectl apply -f on the exact same file works, because it skips empty/null documents. So a manifest that is perfectly valid everywhere else in the ecosystem is rejected by project run.
How can we reproduce it?
cat > prereq.yaml <<'EOF'
# A header comment describing this file.
# It spans a few lines before the first resource.
---
apiVersion: v1
kind: Namespace
metadata:
name: demo
EOF
# Fails:
crossplane project run --init-resources prereq.yaml
# Error: encountered an invalid or empty raw resource
# The identical file applies fine with kubectl:
kubectl apply --dry-run=client -f prereq.yaml
Deleting the leading comment lines (so the file starts at the first resource), or moving the comment to after the first ---, makes the error go away. The same applies to --extra-resources.
Root cause
The YAML stream loader splits on --- and drops only byte-empty chunks, but a comment-only chunk is non-empty text, so it survives, unmarshals to an empty RawExtension, and ApplyResources then treats that empty resource as fatal:
-
cmd/crossplane/render/load.go — LoadYAMLStreamFromFile reads documents with k8s.io/apimachinery/pkg/util/yaml.NewYAMLReader and skips only chunks where len(bytes) == 0. The leading # ... block (before the first ---) is non-empty bytes, so it is returned as a document.
-
cmd/crossplane/project/run.go — each document is sigs.k8s.io/yaml.Unmarshal'd into a runtime.RawExtension. A comment-only document is valid YAML that unmarshals to null, leaving RawExtension.Raw empty (no error at this step).
-
internal/project/install.go — ApplyResources hard-fails on it:
for _, raw := range resources {
if len(raw.Raw) == 0 {
return errors.New("encountered an invalid or empty raw resource")
}
...
Suggested fix
Skip empty raw resources instead of erroring, matching how kubectl and the rest of the ecosystem treat empty/null documents. In ApplyResources:
if len(raw.Raw) == 0 {
continue
}
That single spot covers both --init-resources and --extra-resources. Happy to open a PR with this plus a regression test if the approach looks right.
What environment did it happen in?
- Crossplane CLI version: v2.4.0 (also present on current
main, 5342ad7 / v2.5.0-rc.0 — the ApplyResources code is unchanged)
- Platform: reproduced on
darwin/arm64 and linux/amd64 (the logic is platform-independent)
- Crossplane version: n/a (fails client-side before contacting a control plane)
What happened?
crossplane project run --init-resources <file>(and--extra-resources) fails with:whenever the manifest begins with a comment block before the first
---document separator — i.e. a file-level header comment, which is a very common convention.kubectl apply -fon the exact same file works, because it skips empty/null documents. So a manifest that is perfectly valid everywhere else in the ecosystem is rejected byproject run.How can we reproduce it?
Deleting the leading comment lines (so the file starts at the first resource), or moving the comment to after the first
---, makes the error go away. The same applies to--extra-resources.Root cause
The YAML stream loader splits on
---and drops only byte-empty chunks, but a comment-only chunk is non-empty text, so it survives, unmarshals to an emptyRawExtension, andApplyResourcesthen treats that empty resource as fatal:cmd/crossplane/render/load.go—LoadYAMLStreamFromFilereads documents withk8s.io/apimachinery/pkg/util/yaml.NewYAMLReaderand skips only chunks wherelen(bytes) == 0. The leading# ...block (before the first---) is non-empty bytes, so it is returned as a document.cmd/crossplane/project/run.go— each document issigs.k8s.io/yaml.Unmarshal'd into aruntime.RawExtension. A comment-only document is valid YAML that unmarshals tonull, leavingRawExtension.Rawempty (no error at this step).internal/project/install.go—ApplyResourceshard-fails on it:Suggested fix
Skip empty raw resources instead of erroring, matching how
kubectland the rest of the ecosystem treat empty/null documents. InApplyResources:That single spot covers both
--init-resourcesand--extra-resources. Happy to open a PR with this plus a regression test if the approach looks right.What environment did it happen in?
main,5342ad7/ v2.5.0-rc.0 — theApplyResourcescode is unchanged)darwin/arm64andlinux/amd64(the logic is platform-independent)