{"record":{"id":"e8c907f943a3651c","repo":"louthy/language-ext","slug":"typeof-fail-name-must-be-a-monoid","errorCode":null,"errorMessage":"{typeof(FAIL).Name} must be a Monoid","messagePattern":"(.+?) must be a Monoid","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/Monads/Alternative Monads/Validation/Trait/Validation.TraitImpl.cs","lineNumber":68,"sourceCode":"        Validation.SuccessI<FAIL, A>(value);\n\n    static K<Validation<FAIL>, B> Applicative<Validation<FAIL>>.Apply<A, B>(\n        K<Validation<FAIL>, Func<A, B>> mf,\n        K<Validation<FAIL>, A> ma) =>\n        mf.ApplyI(ma, SemigroupInstance<FAIL>.Instance);\n\n    static K<Validation<FAIL>, B> Applicative<Validation<FAIL>>.Apply<A, B>(\n        K<Validation<FAIL>, Func<A, B>> mf,\n        Memo<Validation<FAIL>, A> ma) =>\n        mf.ApplyI(ma.Value, SemigroupInstance<FAIL>.Instance);\n\n    static K<Validation<FAIL>, A> Alternative<Validation<FAIL>>.Empty<A>() =>\n        MonoidInstance<FAIL>.Instance switch\n        {\n            { IsSome: true, Value: { } monoid } =>\n                Validation.FailI<FAIL, A>(monoid.Empty),\n\n            _ => throw new NotSupportedException($\"{typeof(FAIL).Name} must be a Monoid\")\n        };\n\n    static K<Validation<FAIL>, A> MonoidK<Validation<FAIL>>.Empty<A>() =>\n        MonoidInstance<FAIL>.Instance switch\n        {\n            { IsSome: true, Value: { } monoid } =>\n                Validation.FailI<FAIL, A>(monoid.Empty),\n\n            _ => throw new NotSupportedException($\"{typeof(FAIL).Name} must be a Monoid\")\n        };\n\n    static K<Validation<FAIL>, A> SemigroupK<Validation<FAIL>>.Combine<A>(\n        K<Validation<FAIL>, A> ma,\n        K<Validation<FAIL>, A> mb) =>\n        ma.As().CombineFirst(mb.As(), SemigroupInstance<FAIL>.Instance);\n\n    static K<Validation<FAIL>, A> Choice<Validation<FAIL>>.Choose<A>(\n        K<Validation<FAIL>, A> ma,","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/Monads/Alternative Monads/Validation/Trait/Validation.TraitImpl.cs#L50-L86","documentation":"The Alternative instance's Empty for Validation<FAIL> requires FAIL to be a Monoid so it can produce an empty failure value. When MonoidInstance<FAIL> resolves to none, the trait implementation throws NotSupportedException stating the FAIL type must be a Monoid.","triggerScenarios":"Invoking the Alternative.Empty<A>() member for K<Validation<FAIL>, A> (e.g. via empty()/Prelude.empty or generic Alternative combinators) where FAIL has no registered Monoid instance.","commonSituations":"Using Validation with a custom FAIL type (e.g. string, custom error record) that lacks a Monoid derivation; calling generic code that requires Alternative.Empty on Validation; upgrading LanguageExt where instance resolution became stricter.","solutions":["Provide a Monoid instance for FAIL (implement Monoid<FAIL> with Empty and Append, or derive via traits/deriving)","Use a FAIL type that already has a Monoid (e.g. Seq<string> / Error types with mempty)","Avoid Alternative.Empty for Validation — construct failures with Validation.Fail directly","Register the instance in the trait-collection initialization so MonoidInstance<FAIL>.Instance is Some"],"exampleFix":"// before\nvar e = empty<Validation<Fail>, int>(); // NotSupportedException: Fail must be a Monoid\n\n// after\npublic struct FailMonoid : Monoid<Fail>\n{\n    public Fail Empty => Fail.Empty;\n    public Fail Append(Fail x, Fail y) => x.Combine(y);\n}\n// then register/derive so MonoidInstance<Fail> resolves, and call empty<Validation<Fail>, int>()","handlingStrategy":"validation","validationCode":"var ok = MonoidInstance<FAIL>.Instance is { IsSome: true };\nif (!ok) throw new InvalidOperationException(\"FAIL must have a Monoid before Alternative.Empty\");","typeGuard":"bool HasMonoid<FAIL>() => MonoidInstance<FAIL>.Instance.IsSome;","tryCatchPattern":"try { var e = empty<Validation<FAIL>, A>(); }\ncatch (NotSupportedException ex) when (ex.Message.EndsWith(\"must be a Monoid\")) { var e = Validation.Fail<FAIL, A>(default!); }","preventionTips":["Always give FAIL types a Monoid instance","Use error types with existing Monoids (Seq<string>, etc.)","Check instance resolution in generic helper code","Document Monoid requirements on custom error types"],"tags":["csharp","languageext","validation","monoid","typeclass"],"backgroundTag":"missing-dependency","analyzedSha":"2f0e3628242889774d4141960a35671a0280051f","analyzedAt":"2026-09-15T03:31:55.716Z","contentChangedAt":"2026-09-15T03:31:55.716Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}