{"record":{"id":"2ca332272eb0de72","repo":"vitessio/vitess","slug":"failed-to-marshal-pk-fields-and-value-into-query-r-2ca332","errorCode":null,"errorMessage":"failed to marshal pk fields and value into query result: %s","messagePattern":"failed to marshal pk fields and value into query result: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/vcopier_atomic.go","lineNumber":205,"sourceCode":"\t\t\t\t\"insert into _vt.copy_state (lastpk, vrepl_id, table_name) values (%a, %s, %s)\", \":lastpk\",\n\t\t\t\tstrconv.Itoa(int(vc.vr.id)),\n\t\t\t\tencodeString(tableName),\n\t\t\t)\n\t\t\taddLatestCopyState := buf.ParsedQuery()\n\t\t\tcopyWorkQueue.open(addLatestCopyState, pkfields, tablePlan)\n\t\t}\n\t\t// When rowstreamer has finished streaming all rows, we get a callback with empty rows.\n\t\tif len(resp.Rows) == 0 {\n\t\t\treturn nil\n\t\t}\n\t\t// Get the last committed pk into a loggable form.\n\t\tlastpkbuf, merr := prototext.Marshal(&querypb.QueryResult{\n\t\t\tFields: pkfields,\n\t\t\tRows:   []*querypb.Row{lastpk},\n\t\t})\n\n\t\tif merr != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal pk fields and value into query result: %s\", merr.Error())\n\t\t}\n\t\tlastpkbv = map[string]*querypb.BindVariable{\n\t\t\t\"lastpk\": {\n\t\t\t\tType:  sqltypes.VarBinary,\n\t\t\t\tValue: lastpkbuf,\n\t\t\t},\n\t\t}\n\t\tlog.Info(fmt.Sprintf(\"copying table %s with lastpk %v\", tableName, lastpkbv))\n\t\t// Prepare a vcopierCopyTask for the current batch of work.\n\t\tcurrCh := make(chan *vcopierCopyTaskResult, 1)\n\n\t\tif parallelism > 1 {\n\t\t\tresp = resp.CloneVT()\n\t\t}\n\t\tcurrT := newVCopierCopyTask(newVCopierCopyTaskArgs(resp.Rows, resp.Lastpk))\n\n\t\t// Send result to the global resultCh and currCh. resultCh is used by\n\t\t// the loop to return results to VStreamRows. currCh will be used to","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/vcopier_atomic.go#L187-L223","documentation":"This error is thrown during VReplication copy when marshalling the primary-key fields and last copied row into a querypb.QueryResult (via prototext.Marshal) fails. The marshalled result is bound as the :lastpk bind variable in the next copy batch query, so a marshal failure means the copy-continuation state cannot be built. It is effectively an internal/serialization error, since querypb types normally marshal cleanly.","triggerScenarios":"prototext.Marshal fails on the constructed &querypb.QueryResult{Fields: pkfields, Rows: []*querypb.Row{lastpk}} in vcopier's copy loop — e.g. malformed or nil field/row contents fed into the query result used for the lastpk bind variable.","commonSituations":"Corrupted or empty source table schema/primary key info during MoveTables/VCopy; a source row whose field descriptors do not match the row data; bugs in custom or filtered copy flows supplying inconsistent pkfields.","solutions":["Inspect the %s detail (the underlying merr) in the error message to identify which field/value failed to marshal","Verify the source table's primary key columns exist and their types match what vreplication discovered (check SHOW CREATE TABLE on source vs the copied schema)","Retry the workflow; if reproducible, collect the exact table/columns and file a Vitess issue with the marshal error text","Check the Vitess version for known vcopier serialization bugs and upgrade to a patched release"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before starting/retrying a copy workflow, verify the source PK schema is discoverable\ncols := vtctldClient.GetWorkflow(workflowName).CopyState[table]\nif len(cols.PKColumns) == 0 {\n    return fmt.Errorf(\"table %s has no discoverable primary key; fix schema before copy\", table)\n}","typeGuard":null,"tryCatchPattern":"err := vtctldClient.WorkflowStart(...)\nif err != nil && strings.Contains(err.Error(), \"failed to marshal pk fields\") {\n    // inspect merr detail, verify source schema, then retry\n    log.Error(\"copy marshal failure\", slog.Any(\"error\", err))\n}","preventionTips":["Ensure every copied table has a well-defined primary key matching between source and target","Keep source and target schemas in sync before starting MoveTables/VCopy","Watch for prototext/querypb-related fixes in release notes and stay on a current patch release"],"tags":["vreplication","serialization","prototext","copy-workflow"],"backgroundTag":"protobuf-marshal-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}