From 6d1a3bb639313b6f862b2e52d70b918befe2cf4a Mon Sep 17 00:00:00 2001 From: Vibhav Bobade Date: Wed, 29 Apr 2026 18:36:10 +0530 Subject: [PATCH] fix(crafter): surface auto-discovery errors instead of masking them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix variable shadowing in AddMaterialContactFreeWithAutoDetectedKind: m, err := (loop-scoped) → m, err = (outer-scoped) so the error from the last failed kind probe is propagated to the caller instead of always being nil. Also break early on protovalidate.ValidationError during auto-discovery so schema-level failures (e.g. invalid material name) are surfaced immediately instead of being masked by the kind-probing loop. Fixes: chainloop-dev/chainloop#2394 Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Vibhav Bobade --- pkg/attestation/crafter/crafter.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pkg/attestation/crafter/crafter.go b/pkg/attestation/crafter/crafter.go index ed7a42f24..86851374a 100644 --- a/pkg/attestation/crafter/crafter.go +++ b/pkg/attestation/crafter/crafter.go @@ -617,30 +617,36 @@ func (c *Crafter) IsMaterialInContract(key string) bool { // AddMaterialContactFreeWithAutoDetectedKind adds a material to the crafting state checking the incoming material matches any of the // supported types in validation order. If the material is not found it will return an error. func (c *Crafter) AddMaterialContactFreeWithAutoDetectedKind(ctx context.Context, attestationID, name, value string, casBackend *casclient.CASBackend, runtimeAnnotations map[string]string) (*api.Attestation_Material, error) { - var err error + var ( + err error + m *api.Attestation_Material + ) for _, kind := range schemaapi.CraftingMaterialInValidationOrder { - m, err := c.AddMaterialContractFree(ctx, attestationID, kind.String(), name, value, casBackend, runtimeAnnotations) + m, err = c.AddMaterialContractFree(ctx, attestationID, kind.String(), name, value, casBackend, runtimeAnnotations) if err == nil { - // Successfully added material, return the kind return m, nil } c.Logger.Debug().Err(err).Str("kind", kind.String()).Msg("failed to add material") - // Handle base error for upload and craft errors except the opening file error - // TODO: have an error to detect validation error instead var policyError *policies.PolicyError if errors.Is(err, materials.ErrBaseUploadAndCraft) || errors.As(err, &policyError) { return nil, err } - // This is a final error, we detected the kind if v1.IsAttestationStateErrorConflict(err) { return nil, err } + + // Proto-validation errors (e.g. invalid material name) are schema-level + // failures, not kind mismatches. Stop probing immediately so the real + // error is surfaced to the user instead of being masked by the loop. + var valErr *protovalidate.ValidationError + if errors.As(err, &valErr) { + return nil, err + } } - // Return an error if no material could be added return nil, fmt.Errorf("failed to auto-discover material kind: %w", err) }