{"record":{"id":"3cfaf68da96a74e5","repo":"ruvnet/ruflo","slug":"q-learning-encoder-version-mismatch-persisted","errorCode":null,"errorMessage":"[Q-Learning] Encoder version mismatch (persisted=${persistedEncoder}, current=${ENCODER_VERSION}); resetting Q-table (see #2239).","messagePattern":"\\[Q-Learning\\] Encoder version mismatch \\(persisted=(.+?), current=(.+?)\\); resetting Q-table \\(see #2239\\)\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/ruvector/q-learning-router.ts","lineNumber":278,"sourceCode":"      }\n      const data = readFileSync(modelPath, 'utf-8');\n      const model: PersistedModel = JSON.parse(data);\n\n      // Validate version compatibility\n      if (!model.version || !model.version.startsWith('1.')) {\n        console.warn(`[Q-Learning] Incompatible model version: ${model.version}`);\n        return false;\n      }\n\n      // #2239 — Encoder-version migration guard. v1 state keys were computed\n      // by a fold that silently dropped the keyword block, so they cannot be\n      // matched by v2 lookups. Skip the qTable import on mismatch (keep\n      // stats/epsilon so learning curve survives a restart).\n      const persistedEncoder = model.encoderVersion ?? 1;\n      if (persistedEncoder === ENCODER_VERSION) {\n        this.import(model.qTable);\n      } else {\n        console.warn(\n          `[Q-Learning] Encoder version mismatch (persisted=${persistedEncoder}, current=${ENCODER_VERSION}); resetting Q-table (see #2239).`,\n        );\n      }\n\n      // Restore stats\n      this.stepCount = model.stats.stepCount || 0;\n      this.updateCount = model.stats.updateCount || 0;\n      this.avgTDError = model.stats.avgTDError || 0;\n      this.epsilon = model.stats.epsilon || this.config.explorationInitial;\n      this.totalExperiences = model.metadata?.totalExperiences || 0;\n\n      return true;\n    } catch (err) {\n      console.warn(`[Q-Learning] Failed to load model: ${err}`);\n      return false;\n    }\n  }\n","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/ruvector/q-learning-router.ts#L260-L296","documentation":"Log warning in loadModel (issue #2239): the persisted state-key encoder version differs from the current one, so old Q-table entries were hashed under a different key scheme; the qTable import is skipped (stats/epsilon kept) to avoid silently unmatched lookups.","triggerScenarios":"Thrown at v3/@claude-flow/cli/src/ruvector/q-learning-router.ts:278 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["No action needed; the Q-table was reset because the encoder changed. Re-train, or pin ENCODER_VERSION to keep old tables (see #2239)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}