update the unknown error

pull/38240/head
sahar-azizighannad 2 months ago
parent c6d6156212
commit 93bc487fae

@ -477,12 +477,8 @@ func evalVariableValidation(validation *stackconfig.CheckRule, hclCtx *hcl.EvalC
const errInvalidValue = "Invalid value for variable"
var diags tfdiags.Diagnostics
// Evaluate both condition and error message up front. The error message is
// always inspected for structural problems (sensitive/ephemeral marks), not only
// when the condition fails.
result, moreDiags := validation.Condition.Value(hclCtx)
diags = diags.Append(moreDiags)
errorValue, errorDiags := validation.ErrorMessage.Value(hclCtx)
if moreDiags.HasErrors() {
// If we couldn't evaluate the condition at all (syntax error, etc.),
@ -529,27 +525,24 @@ func evalVariableValidation(validation *stackconfig.CheckRule, hclCtx *hcl.EvalC
// The marks don't affect the validation result, only how we handle the error message.
result, _ = result.Unmark()
// Always process and validate the error_message expression, even when the condition
// passes — an invalid error message (sensitive, ephemeral, non-string, etc.) should
// be flagged regardless of whether the check succeeds or fails.
// Always evaluate the error_message expression, even when the condition passes —
// unknown, sensitive, or ephemeral values in the message are structural problems
// regardless of whether the check succeeds or fails.
errorValue, errorDiags := validation.ErrorMessage.Value(hclCtx)
diags = diags.Append(errorDiags)
var errorMessage string
if !errorDiags.HasErrors() {
if !errorValue.IsKnown() {
if !result.True() {
// An unknown error message is only a problem when the condition actually
// fails, since we need to display it to the user.
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid error message",
Detail: "Unsuitable value for error message: expression refers to values that won't be known until the apply phase.",
Subject: validation.ErrorMessage.Range().Ptr(),
Expression: validation.ErrorMessage,
EvalContext: hclCtx,
})
return diags
}
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid error message",
Detail: "Unsuitable value for error message: expression refers to values that won't be known until the apply phase.",
Subject: validation.ErrorMessage.Range().Ptr(),
Expression: validation.ErrorMessage,
EvalContext: hclCtx,
})
return diags
} else if !errorValue.IsNull() {
errorValue, err = convert.Convert(errorValue, cty.String)
if err != nil {

@ -665,9 +665,12 @@ func TestEvalVariableValidation(t *testing.T) {
// --- Unknown error message ---
t.Run("error message unknown, condition fails → Invalid error message (no failure diag)", func(t *testing.T) {
// We must flag the unknown error message but must NOT also emit
// "Invalid value for variable" because we return early.
t.Run("error message unknown, condition fails → Invalid error message only", func(t *testing.T) {
// An unknown error_message is always a structural problem: the validation
// block is invalid regardless of whether the condition passes or fails,
// because Terraform can never safely display the message.
// We return early on the unknown message, so "Invalid value for variable"
// must NOT also be emitted.
rule := makeFakeRule(
hcltest.MockExprLiteral(cty.False),
hcltest.MockExprLiteral(cty.UnknownVal(cty.String)),
@ -684,16 +687,26 @@ func TestEvalVariableValidation(t *testing.T) {
}
})
t.Run("error message unknown, condition passes → no diagnostic about error message", func(t *testing.T) {
// Unknown error message is only a problem when the condition actually
// fails (because we'd need to display it). When the condition passes
// the unknown error message must be silently ignored.
t.Run("error message unknown, condition passes → Invalid error message only", func(t *testing.T) {
// An unknown error_message is always a structural problem: the validation
// block is invalid regardless of whether the condition passes or fails,
// because Terraform can never safely display the message.
// We return early on the unknown message, so "Invalid value for variable"
// must NOT be emitted even though the condition passed.
rule := makeFakeRule(
hcltest.MockExprLiteral(cty.True),
hcltest.MockExprLiteral(cty.UnknownVal(cty.String)),
)
diags := evalVariableValidation(rule, makeVarCtx(cty.StringVal("good")), valueRange)
assertNoDiags(t, diags)
assertMatchingDiag(t, diags, func(d tfdiags.Diagnostic) bool {
return d.Severity() == tfdiags.Error &&
d.Description().Summary == "Invalid error message"
})
for _, d := range diags {
if d.Description().Summary == "Invalid value for variable" {
t.Errorf("unexpected 'Invalid value for variable' when error message is unknown")
}
}
})
// --- Sensitive variable value in condition expression ---

Loading…
Cancel
Save