{"record":{"id":"fdae000275703ed0","repo":"dotnet/orleans","slug":"error-when-trying-to-convert-grain-id","errorCode":null,"errorMessage":"Error when trying to convert grain Id","messagePattern":"Error when trying to convert grain Id","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Dashboard/Orleans.Dashboard/Implementation/Helpers/GrainStateHelper.cs","lineNumber":50,"sourceCode":"                grainId = Convert.ToInt64(splitedGrainId.First());\n                keyExtension = splitedGrainId.Last();\n            }\n            else if (implementationType.IsAssignableTo(typeof(IGrainWithIntegerKey)))\n            {\n                grainId = Convert.ToInt64(id);\n            }\n            else if (implementationType.IsAssignableTo(typeof(IGrainWithGuidKey)))\n            {\n                grainId = Guid.Parse(id);\n            }\n            else if (implementationType.IsAssignableTo(typeof(IGrainWithStringKey)))\n            {\n                grainId = id;\n            }\n        }\n        catch (Exception ex)\n        {\n            throw new Exception(\"Error when trying to convert grain Id\", ex);\n        }\n\n        return (grainId, keyExtension);\n    }\n\n    public static IEnumerable<Type> GetPropertiesAndFieldsForGrainState(Type implementationType)\n    {\n        var impProperties = implementationType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);\n\n        var impFields = implementationType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);\n\n        var filterProps = impProperties\n                            .Where(w => w.PropertyType.IsAssignableTo(typeof(IStorage)))\n                            .Select(s => s.PropertyType.GetGenericArguments().First());\n\n        var filterFields = impFields\n                            .Where(w => w.FieldType.IsAssignableTo(typeof(IStorage)))\n                            .Select(s => s.FieldType.GetGenericArguments().First());","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Dashboard/Orleans.Dashboard/Implementation/Helpers/GrainStateHelper.cs#L32-L68","documentation":"A generic System.Exception with message 'Error when trying to convert grain Id' that wraps any exception thrown while parsing a grain id inside GrainStateHelper.GetGrainId. The inner try/catch around Guid.Parse/Convert.ToInt64/id-assignment catches FormatException, OverflowException, etc., and re-wraps them, losing the specific type but preserving InnerException.","triggerScenarios":"Any parse failure inside the id-conversion try block: Guid.Parse on a non-guid string, Convert.ToInt64 on a non-numeric string, or an id that does not match the grain's key marker. The catch is broad (Exception), so all such failures funnel here.","commonSituations":"Dashboard passes a string id that matches the comma format but whose first segment is the wrong type (e.g. a guid passed to an integer-compound grain), a corrupted/truncated id, or a mismatched implementationType causing the wrong parser to run.","solutions":["Inspect InnerException for the real parse error (FormatException/OverflowException) to identify which segment failed.","Pre-validate each segment against the grain's key type (Guid.TryParse / long.TryParse) before calling.","Ensure the implementationType passed to GetGrainId is the actual grain type backing the id."],"exampleFix":"// before\ntry { var (gid, ext) = GrainStateHelper.GetGrainId(rawId, type); }\ncatch (Exception ex) { /* opaque */ }\n\n// after\nvar parts = rawId.Split(',');\nif (!Guid.TryParse(parts[0], out var g))\n    return BadRequest(\"primary key is not a guid\");\nvar (gid, ext) = GrainStateHelper.GetGrainId(rawId, type);\n// (still wrap in try/catch to read ex.InnerException if needed)","handlingStrategy":"try-catch","validationCode":"var parts = id.Split(',');\nif (parts.Length != 2 || !Guid.TryParse(parts[0], out _))\n    return BadRequest(\"primary key parse would fail\");","typeGuard":"static bool IsParsablePrimaryKey(string id, Type implType) =>\n    implType.IsAssignableTo(typeof(IGrainWithGuidKey)) ? Guid.TryParse(id.Split(',').First(), out _) :\n    implType.IsAssignableTo(typeof(IGrainWithIntegerKey)) ? long.TryParse(id.Split(',').First(), out _) : true;","tryCatchPattern":"try { var (gid, ext) = GrainStateHelper.GetGrainId(id, type); }\ncatch (Exception ex) when (ex.Message.Contains(\"Error when trying to convert grain Id\"))\n{ logger.LogError(ex.InnerException, \"grain id parse failed\"); return BadRequest(\"invalid id\"); }","preventionTips":["Pre-parse the primary key segment against the grain's key type","Read InnerException for the real FormatException/OverflowException","Confirm implementationType matches the id's shape"],"tags":["dashboard","grain-id","parsing","error-wrapping"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}