microsoft/aspire · error · InvalidOperationException

Handle ' ' not found in registry

Error message

Handle '{handleId}' not found in registry

What it means

HandleRegistry.GetObject looks up the object stored for an ATS handle ID and throws this InvalidOperationException when the ID has no entry in the registry. It signals the caller passed a handle that was never registered or was removed/disposed.

Solutions

  1. Re-register the object (or re-request the handle from the remote host) before calling GetObject.
  2. Verify the handle ID is passed unmodified from where Register returned it.
  3. Use TryGetObject or Handles/ContainsHandle-style existence check first if available.
  4. If handles cross process lifetimes, re-acquire handles after each remote host restart instead of persisting them.

Example fix

// before
var obj = registry.GetObject(handleId); // throws if stale

// after
if (!registry.ContainsHandle(handleId))
{
    handleId = ReRegisterObject(remoteHost);
}
var obj = registry.GetObject(handleId);
Defensive patterns

Strategy: validation

Validate before calling

if (registry is null || string.IsNullOrWhiteSpace(handleId))
    throw new ArgumentException("Handle ID must be non-empty before lookup.");
// pre-check (registry exposes handle enumeration/contains semantics)
if (!registry.Handles.Any(h => h.Id == handleId))
    throw new InvalidOperationException($"Handle '{handleId}' is stale; re-register the object.");

Type guard

bool TryGetRegistered(Aspire.Hosting.RemoteHost.Ats.HandleRegistry registry, string id, out object? obj)
{
    obj = null;
    if (!registry.Handles.Any(h => h.Id == id)) return false;
    try { obj = registry.GetObject(id); return true; }
    catch (InvalidOperationException) { return false; }
}

Try / catch

try
{
    var obj = registry.GetObject(handleId);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("not found in registry"))
{
    handleId = ReRegisterAndAcquireHandle(remoteHost);
    var obj = registry.GetObject(handleId);
}

Prevention

When it happens

Trigger: Calling GetObject(handleId) (or the typed overload, which calls it first) with an ID not present in _handles — e.g. a stale handle from a previous session or a mistyped ID string.

Common situations: Client cached a handle across a remote-host restart (registry is per-process); handle was unregistered/disposed earlier; ID string truncated or altered in transit.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/46da68e98c919deb. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.RemoteHost/Ats/HandleRegistry.cs:81

            return true;
        }

        obj = null;
        typeId = null;
        return false;
    }

    /// <summary>
    /// Gets the underlying object for a handle.
    /// </summary>
    /// <param name="handleId">The handle ID.</param>
    /// <returns>The underlying object.</returns>
    /// <exception cref="InvalidOperationException">Thrown if the handle is not found.</exception>
    public object GetObject(string handleId)
    {
        if (!_handles.TryGetValue(handleId, out var entry))
        {
            throw new InvalidOperationException($"Handle '{handleId}' not found in registry");
        }
        return entry.Object;
    }

    /// <summary>
    /// Gets the underlying object for a handle, cast to the specified type.
    /// </summary>
    /// <typeparam name="T">The expected type.</typeparam>
    /// <param name="handleId">The handle ID.</param>
    /// <returns>The underlying object.</returns>
    /// <exception cref="InvalidOperationException">Thrown if the handle is not found or type doesn't match.</exception>
    public T GetObject<T>(string handleId) where T : class
    {
        var obj = GetObject(handleId);
        if (obj is not T typed)
        {
            throw new InvalidOperationException(
                $"Handle '{handleId}' contains {obj.GetType().FullName}, expected {typeof(T).FullName}");

View on GitHub (pinned to 25830f84bd)