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
- 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.
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
- 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
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
- Inform grain id in format `{ id},{additionalKey}`
- Inform grain id in format {id},{additionalKey}
- Embedded resource not found: {fullResourceName}
- Orleans Dashboard services have not been registered. Please
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/fdae000275703ed0.
Report an issue: GitHub.