# Mastra 'invocation.errorText?.trim is not a function': fixed in @mastra/memory 1.39.1

*Disclosure: I work on MemorySync (I'm Mohammed, the founder). I drafted this page with AI assistance and checked it against the source issue, its linked fix and the docs listed under Sources on Oct 28, 2026. I read the issue, the fix PR and the package changelog; I didn't run Mastra for this page.*

## The question

[mastra-ai/mastra#28407](https://github.com/mastra-ai/mastra/issues/28407), "Memory TokenCounter crashes on persisted object-valued errorText (still present in 1.39.0)", opened Oct 26, 2026:

```text
TypeError: invocation.errorText?.trim is not a function
```

`TokenCounter.countMessagesAsync()` threw it when stored history held a tool invocation whose `errorText` was an object rather than a string, in both the `state: 'result'` + `isError: true` branch and the `state: 'output-error'` branch. The reporter reproduced it on @mastra/memory 1.38.0, 1.39.0 and 1.39.1-alpha.1, with a JSON round trip and no API keys. The TypeScript type says `string`; the problem is older or imported rows that don't match it.

**Status (checked Nov 9, 2026 via the GitHub API):** closed as completed on Oct 26, 2026, by PR [#28440](https://github.com/mastra-ai/mastra/pull/28440), "fix(memory): stop Observational Memory from crashing on object-valued tool errorText". The @mastra/memory changelog lists the fix under **1.39.1** (published Oct 28, 2026). As of Nov 9, 2026 the npm `latest` is **1.41.0**; the fix shipped in 1.39.1 and later. I didn't re-run Mastra on 1.41.0.

> **Skip the memory plumbing around this fix.** Once the fix below is in, the [MemorySync Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function) shows how to add per-user memory with MemorySync. MemorySync doesn't fix this error itself. When you're ready, [see MemorySync](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function). Founding offer: use code FOUNDING30 for 30% off Starter for your first 3 months (Settings → Billing).

## Why it hurts more than one turn

Per the PR, there were two crash sites, both calling `errorText?.trim()`:

- `TokenCounter.countMessagesAsync()` (`token-counter.ts`)
- `formatMessagesForObserver()` (`observer-agent.ts`), which threw `TypeError: inv.errorText?.trim is not a function`

Because the bad row stays in the thread, "either error stopped Observational Memory on every later turn," and fixing only one of them didn't help.

## Fix

1. **Upgrade.** The changelog's 1.39.1 entry includes a peer-dependency change: if your package manager reports a peer conflict, upgrade @mastra/core first, then memory:

```bash
pnpm add @mastra/core@^1.80.0
pnpm add @mastra/memory@latest
```

2. **If you can't upgrade yet**, normalise stored rows before Mastra reads them: for tool invocations where `errorText` isn't a string, store `JSON.stringify(errorText)` instead. The reporter's table shows 1.38.0 with that kind of normalisation working, with token counts matching the string control.

3. **Look for the source of object errors.** Rows written by older code paths or imported from elsewhere are the usual suspects per the issue. Fixing the writer keeps new rows clean.

## Common questions

**Do I need to delete the thread?**
Not after upgrading: the PR adds a shared helper (`toolErrorTextToString()`) that normalises the value when reading, so existing rows are handled.

**Does it affect Mastra without Observational Memory?**
The crash sites are in Observational Memory's token counter and observer, per the PR.

## Skip the plumbing with MemorySync

Disclosure: I build MemorySync.

It doesn't touch Mastra's thread storage, so the upgrade is still the fix. The [MemorySync Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function) documents processors that recall context before each model call and send the user's message for fact extraction after it; assistant replies aren't stored. For an overview of MemorySync, see [the MemorySync homepage](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function).

From the guide:

**Unverified (not run):**

```bash
npm install memorysync-mastra @mastra/core
```

```typescript
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";
import { createMemorySyncProcessors } from "memorysync-mastra";

const { inputProcessor, outputProcessor } = createMemorySyncProcessors({
  userId: "customer-7",     // per-end-user scoping
  sessionId: "thread-42",   // groups the stored facts by thread
});

const agent = new Agent({
  id: "assistant",
  name: "Assistant",
  instructions: "You are a helpful assistant.",
  model: openai("your-model"),
  inputProcessors: [inputProcessor],
  outputProcessors: [outputProcessor],
});

// First conversation
await agent.generate("I'm vegetarian and I fly aisle.");

// Any later call — same user, any thread, any model
const { text } = await agent.generate(
  "Book my trip: flight plus a dinner spot.",
);
// The model already saw: vegetarian, aisle seat — injected from memory.
```

*Snippet adapted from the [MemorySync Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function); I haven't run it for this page.*

**Try it:** MemorySync is optional here: the steps above work without it. If you want the memory layer from the snippet, [see MemorySync](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function), create an API key in the dashboard and drop the snippet into your agent.

## Sources

- mastra-ai/mastra#28407 (closed 2026-10-26, completed; read 2026-10-28)
- mastra-ai/mastra#28440 (merged 2026-10-26)
- @mastra/memory CHANGELOG.md on main, 1.39.1 entry; npm `latest` 1.41.0 as of 2026-11-09 (fix first shipped in 1.39.1; I didn't re-run 1.41.0)
- MemorySync docs: docs.memorysync.io/guides/mastra

**Next step:** read the [MemorySync Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function), then [see MemorySync](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_mastra-observational-memory-errortext-trim-is-not-a-function). Founding offer: use code FOUNDING30 for 30% off Starter for your first 3 months (Settings → Billing).

