{"record":{"id":"4bc1022fcb04be02","repo":"gastownhall/beads","slug":"proxied-server-provider-t-does-not-offer-the-pers","errorCode":null,"errorMessage":"proxied-server provider %T does not offer the persistent-memory surface","messagePattern":"proxied-server provider %T does not offer the persistent-memory surface","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/memory.go","lineNumber":55,"sourceCode":"// invocation's proxied-server provider, through the provider's OWN capability\n// accessor — the same two-step proxiedWorkspaceConfig performs.\nfunc proxiedMemories() (memoryops.Memories, error) {\n\tif uowProvider == nil {\n\t\treturn nil, errors.New(\"proxied-server UOW provider not initialized\")\n\t}\n\treturn memoriesFromProvider(uowProvider)\n}\n\n// memoriesFromProvider is that accessor step for a provider the caller names.\n//\n// It takes the provider rather than reading the global one because `bd prime`\n// opens a provider SCOPED to its read — prime is in noDbCommands, so the root\n// pre-run opens nothing — and one spelling of \"ask this provider for the memory\n// surface\" is the whole point of having an accessor at all.\nfunc memoriesFromProvider(provider uow.UnitOfWorkProvider) (memoryops.Memories, error) {\n\tsrc, ok := provider.(uow.MemoriesSource)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"proxied-server provider %T does not offer the persistent-memory surface\", provider)\n\t}\n\treturn src.Memories()\n}\n\n// noteDirectMemoryWrite marks the invocation as having written, which is what\n// the auto-commit epilogue in main.go keys on.\n//\n// It is DIRECT-ROUTE ONLY, and both halves of that matter. A direct memory\n// write lands in the Dolt working set and nothing else commits it, so a verb\n// that forgets to call this stores a memory that exists until the process exits\n// and then sits uncommitted — visible to the session that wrote it and to\n// nothing after. A proxied write already committed inside the role's unit of\n// work, so flagging it there would ask the epilogue to commit a second time on\n// a route with nothing outstanding.\n//\n// The RunEs cannot make that distinction themselves: openMemories hides which\n// route they are on, which is the point. So the guard lives here, once, the way\n// noteDirectConfigWrite does for the settings plane.","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/memory.go#L37-L73","documentation":"memoriesFromProvider asserts that the UnitOfWorkProvider handed to it implements uow.MemoriesSource (a Memories() accessor). The root pre-run deliberately opens nothing for noDbCommands like `bd prime`, so the provider is a proxied/lazy server handle; if that handle does not expose the persistent-memory surface, the code cannot read or write memories and fails with this type-assertion error naming the concrete type %T.","triggerScenarios":"Calling proxiedMemories / primeProxiedMemoryPlane when the proxied-server provider was constructed without the memories capability (e.g. server version predates the memory plane, or the proxy was built from a narrower interface).","commonSituations":"Running `bd prime` against an older daemon that doesn't implement the memory RPC; a proxy wrapping only issue CRUD; mismatched bd client/server versions.","solutions":["Upgrade the bd daemon/server so the proxied provider implements uow.MemoriesSource","Verify client and server versions match (`bd --version` on both sides)","If memories are unavailable intentionally, skip the memory plane instead of calling primeProxiedMemoryPlane","Extend the proxy's provider construction to include the memories source when the backend supports it"],"exampleFix":"// before\nmems, err := memoriesFromProvider(prov)\n// after\nif _, ok := prov.(uow.MemoriesSource); !ok {\n    return nil // memory surface unavailable; proceed without it\n}\nmems, err := memoriesFromProvider(prov)","handlingStrategy":"type-guard","validationCode":"// check the provider capability before use\nif _, ok := prov.(uow.MemoriesSource); !ok { skipMemoryPlane(); }","typeGuard":"function hasMemories(p uow.UnitOfWorkProvider) (uow.MemoriesSource, bool) { src, ok := p.(uow.MemoriesSource); return src, ok }","tryCatchPattern":"mems, err := memoriesFromProvider(prov)\nif err != nil && strings.Contains(err.Error(), \"does not offer the persistent-memory surface\") {\n    return nil // degrade gracefully\n}","preventionTips":["Keep client and server bd versions in sync","Gate memory-plane features on a capability probe","Avoid wrapping providers in narrower interfaces that drop MemoriesSource"],"tags":["interface-assertion","memory","proxy","capability-missing"],"backgroundTag":"capability-not-implemented","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}