dotnet/orleans · error · Exception

Error when trying to convert grain Id

Error message

Error when trying to convert grain Id

What it means

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.

Source

Thrown at src/Dashboard/Orleans.Dashboard/Implementation/Helpers/GrainStateHelper.cs:50

                grainId = Convert.ToInt64(splitedGrainId.First());
                keyExtension = splitedGrainId.Last();
            }
            else if (implementationType.IsAssignableTo(typeof(IGrainWithIntegerKey)))
            {
                grainId = Convert.ToInt64(id);
            }
            else if (implementationType.IsAssignableTo(typeof(IGrainWithGuidKey)))
            {
                grainId = Guid.Parse(id);
            }
            else if (implementationType.IsAssignableTo(typeof(IGrainWithStringKey)))
            {
                grainId = id;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error when trying to convert grain Id", ex);
        }

        return (grainId, keyExtension);
    }

    public static IEnumerable<Type> GetPropertiesAndFieldsForGrainState(Type implementationType)
    {
        var impProperties = implementationType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);

        var impFields = implementationType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);

        var filterProps = impProperties
                            .Where(w => w.PropertyType.IsAssignableTo(typeof(IStorage)))
                            .Select(s => s.PropertyType.GetGenericArguments().First());

        var filterFields = impFields
                            .Where(w => w.FieldType.IsAssignableTo(typeof(IStorage)))
                            .Select(s => s.FieldType.GetGenericArguments().First());

View on GitHub (pinned to fca799fa70)

Solutions

  1. Inspect InnerException for the real parse error (FormatException/OverflowException) to identify which segment failed.
  2. Pre-validate each segment against the grain's key type (Guid.TryParse / long.TryParse) before calling.
  3. Ensure the implementationType passed to GetGrainId is the actual grain type backing the id.

Example fix

// before
try { var (gid, ext) = GrainStateHelper.GetGrainId(rawId, type); }
catch (Exception ex) { /* opaque */ }

// after
var parts = rawId.Split(',');
if (!Guid.TryParse(parts[0], out var g))
    return BadRequest("primary key is not a guid");
var (gid, ext) = GrainStateHelper.GetGrainId(rawId, type);
// (still wrap in try/catch to read ex.InnerException if needed)
Defensive patterns

Strategy: try-catch

Validate before calling

var parts = id.Split(',');
if (parts.Length != 2 || !Guid.TryParse(parts[0], out _))
    return BadRequest("primary key parse would fail");

Type guard

static bool IsParsablePrimaryKey(string id, Type implType) =>
    implType.IsAssignableTo(typeof(IGrainWithGuidKey)) ? Guid.TryParse(id.Split(',').First(), out _) :
    implType.IsAssignableTo(typeof(IGrainWithIntegerKey)) ? long.TryParse(id.Split(',').First(), out _) : true;

Try / catch

try { var (gid, ext) = GrainStateHelper.GetGrainId(id, type); }
catch (Exception ex) when (ex.Message.Contains("Error when trying to convert grain Id"))
{ logger.LogError(ex.InnerException, "grain id parse failed"); return BadRequest("invalid id"); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/fdae000275703ed0. Report an issue: GitHub.