{"record":{"id":"99c3da31d6f5990e","repo":"vitessio/vitess","slug":"vindex-has-no-owner","errorCode":null,"errorMessage":"vindex has no owner","messagePattern":"vindex has no owner","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/workflow/lookup_vindex.go","lineNumber":632,"sourceCode":"\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 {\n\t\ttargetPrimary, err := lv.ts.GetTablet(ctx, targetShard.PrimaryAlias)\n\t\tif err != nil {\n\t\t\treturn err","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/workflow/lookup_vindex.go#L614-L650","documentation":"validateExternalizedVindex requires that a vindex being externalized has an owner. An ownerless vindex cannot be safely taken over by the lookup vindex workflow, since ownership determines who maintains lookup rows during writes, so the check fails with this error.","triggerScenarios":"Running CreateLookupVindex externalization against a vindex whose Vindex.Owner field is empty — the vindex exists in the target vschema but has no owner column vindex association and write_only is not set to true.","commonSituations":"Vindex was created without an --owner flag; vschema hand-edited and the owner field dropped; earlier workflow failed before assigning ownership.","solutions":["Pass the owner table (e.g. --owner user) when creating the lookup vindex so ownership is set","Set the \"owner\" field on the vindex in the target keyspace's vschema, or remove/recreate the vindex properly","If the vindex is intentionally unowned, do not run the externalization workflow for it; use plain Materialize instead"],"exampleFix":"// before\nvtctldclient CreateLookupVindex --target-keyspace lookup commerce \"{'vindexes': {...}}\"\n// after\nvtctldclient CreateLookupVindex --target-keyspace lookup --owner-table user --owner-column id commerce \"{'vindexes': {...}}\"","handlingStrategy":"validation","validationCode":"v, _ := ts.GetVSchema(ctx, targetKS)\nif vi := v.Vindexes[vindexName]; vi != nil && vi.Owner == \"\" {\n    return fmt.Errorf(\"vindex %s has no owner; pass owner table/column or set vschema owner\", vindexName)\n}","typeGuard":"func hasOwner(v *vschemapb.Vindex) bool { return v.Owner != \"\" }","tryCatchPattern":"if err := lv.validateExternalized(ctx, targetShards); err != nil {\n    if strings.Contains(err.Error(), \"no owner\") {\n        return fmt.Errorf(\"recreate the vindex with --owner set: %w\", err)\n    }\n    return err\n}","preventionTips":["Always pass the owner table when creating owned lookup vindexes","Never hand-edit vschema owner fields without verifying them","Run a pre-flight GetVSchema check before externalization workflows"],"tags":["vindex","lookup-vindex","vschema","ownership"],"backgroundTag":"vindex-has-no-owner","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}