{"record":{"id":"159d559e92028345","repo":"vitessio/vitess","slug":"vindex-is-in-write-only-mode","errorCode":null,"errorMessage":"vindex is in write-only mode","messagePattern":"vindex is in write-only mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/workflow/lookup_vindex.go","lineNumber":629,"sourceCode":"\t\t\t\tType: targetVindexType,\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\tif targetVindex == nil {\n\t\terr = vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"column %s not found in target schema %s\",\n\t\t\tsourceVindexColumn, sourceTableDefinition.Schema)\n\t\treturn\n\t}\n\treturn\n}\n\n// validateExternalizedVindex checks if a given vindex is externalized.\n// A vindex is considered externalized if it has an owner and is not in write-only mode.\nfunc (lv *lookupVindex) validateExternalizedVindex(vindex *vschemapb.Vindex) error {\n\twriteOnly, ok := vindex.Params[\"write_only\"]\n\tif ok && writeOnly == \"true\" {\n\t\treturn errors.New(\"vindex is in write-only mode\")\n\t}\n\tif vindex.Owner == \"\" {\n\t\treturn errors.New(\"vindex has no owner\")\n\t}\n\treturn nil\n}\n\n// validateExternalized checks if the vindexes have been externalized\n// and verifies the state of the VReplication workflow on the target shards.\n// It ensures that all streams in the workflow are frozen.\nfunc (lv *lookupVindex) validateExternalized(ctx context.Context, vindexByName map[string]*vschemapb.Vindex, workflowName string, targetShards []*topo.ShardInfo) error {\n\tfor vindexName, vindex := range vindexByName {\n\t\tif err := lv.validateExternalizedVindex(vindex); err != nil {\n\t\t\treturn vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, \"vindex %s has not been externalized yet: %v\", vindexName, err)\n\t\t}\n\t}\n\n\terr := forAllShards(targetShards, func(targetShard *topo.ShardInfo) error {","sourceCodeStart":611,"sourceCodeEnd":647,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/workflow/lookup_vindex.go#L611-L647","documentation":"validateExternalizedVindex checks that a vindex being claimed by a new lookup vindex workflow is safely externalizable. The doc comment says a vindex is externalized if it has an owner and is not write-only, but the implementation rejects write_only=true vindexes with this error — a vindex flagged in write-only mode conflicts with taking ownership via the backfill workflow.","triggerScenarios":"Running CreateLookupVindex with --owner or the externalization path where the target vindex's params contain \"write_only\": \"true\" in the vschema.","commonSituations":"A previous migration left the vindex in write-only mode (mid-migration state) and the operator retries creation; manually setting write_only to keep lookups disabled during backfill and then attempting to externalize.","solutions":["Remove the \"write_only\": \"true\" param from the vindex in the target keyspace's vschema (set it false or delete the param) and retry","Ensure the prior workflow that set write-only mode is complete/cleaned up before externalizing","Verify with `vtctldclient GetVSchema <keyspace>` that vindex params are in the expected state"],"exampleFix":"// before (target vschema)\n\"lv\": {\"type\": \"consistent_lookup_unique\", \"params\": {\"write_only\": \"true\"}, \"owner\": \"user\"}\n// after\n\"lv\": {\"type\": \"consistent_lookup_unique\", \"owner\": \"user\"}","handlingStrategy":"validation","validationCode":"v, _ := ts.GetVSchema(ctx, targetKS)\nif vi := v.Vindexes[vindexName]; vi != nil {\n    if vi.Params[\"write_only\"] == \"true\" {\n        return fmt.Errorf(\"clear write_only on vindex %s before externalizing\", vindexName)\n    }\n}","typeGuard":"func isWriteOnly(v *vschemapb.Vindex) bool { return v.Params[\"write_only\"] == \"true\" }","tryCatchPattern":"if err := lv.validateExternalized(ctx, targetShards); err != nil {\n    if strings.Contains(err.Error(), \"write-only mode\") {\n        return fmt.Errorf(\"finish/clean the prior workflow and clear write_only: %w\", err)\n    }\n    return err\n}","preventionTips":["Complete prior migration workflows before starting externalization","Inspect GetVSchema output for leftover write_only params","Automate removing write_only after backfill completes"],"tags":["vindex","lookup-vindex","vschema","migration"],"backgroundTag":"vindex-write-only-mode","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}