confusing error message when a definition uses a required field in a dynamic field expression
What version of CUE are you using (cue version)?
$ cue version
cue version v0.15.1
CUE language version v0.15.1
Go version go1.25.4
-buildmode exe
-compiler gc
-trimpath true
CGO_ENABLED 0
GOARCH arm64
GOOS darwin
GOARM64 v8.0
Does this issue reproduce with the latest stable release?
Yes, it reproduces starting from v0.15.0-alpha3. It is working correctly on v0.14.2
What did you do?
package test
#Manifest: {
apiVersion!: "v1"
kind!: "__kind"
}
#GeneratorInput: {
(#Manifest.kind): {
(#Manifest.apiVersion): #Manifest
}
}
_input: #GeneratorInput
_input: "__kind": "v1": {
apiVersion: "v1"
kind: "__kind"
}
output: _input[#Manifest.kind][#Manifest.apiVersion]
What did you expect to see?
Running a cue export for this snippet should output:
{
"output": {
"apiVersion": "v1",
"kind": "__kind"
}
}
What did you see instead?
_input."__kind": field not allowed:
./test.cue:15:9
Removing the required markers ! from apiVersion and kind makes it work again.
Bisected this issue to commit a25fb94136c3c3e530a0341715e31d8ccd21ba8a
Reduced to the following testscript:
exec cue export in.cue
-- in.cue --
#Object: version!: "v1"
#Output: (#Object.version): #Object
out: #Output
out: v1: version: "v1"
Below are the results with v0.14.2 and master (166a851f1f6337adefd484aff8643f31c9f3b836):
> exec cue-v0.14.2 export in.cue
[stdout]
{
"out": {
"v1": {
"version": "v1"
}
}
}
> exec cue export in.cue
[stderr]
out.v1: field not allowed:
./in.cue:6:6
I also bisected this to a25fb94136c3c3e530a0341715e31d8ccd21ba8a.
I believe this is working as intended; in my reduced example, the selection of #Object.version is an error, because you're accessing a required field that isn't present. As such, #Output ends up not allowing any fields. Perhaps the error here is confusing; it could error at the declaration of #Output, which might be more helpful, but I don't think it should work given the current CUE language spec.
I see a few possible solutions here:
- Declare the string you need to reuse separately, outside of a required field. This is what I would do, as reusing a value from a required field is not a very good setup right now.
- When selecting the required field, "fill it" as a regular field so that you can get its value. For example, in my reduction:
#Output: ((#Object & {version: _}).version): #Object
In other words, the commit that we bisected is a bugfix; older versions of CUE did not correctly apply the required field semantics outlined in the language spec.
With @cuematthew we're in agreement that this should indeed fail, and that commit was a bugfix, but that the error you're seeing now is not ideal. I'll repurpose this issue to track the less-than-ideal error.
That is, the testscript in https://github.com/cue-lang/cue/issues/4192#issuecomment-3566805582 should fail with a message like the one I get if I make #Output a non-definition like Output:
Output: key value of dynamic field must be concrete, found _|_(Output: required field missing: version):