{"record":{"id":"792e92eaf364bd2e","repo":"Tencent/WeKnora","slug":"empty-embed-visitor-id","errorCode":null,"errorMessage":"empty embed visitor id","messagePattern":"empty embed visitor id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/types/principal.go","lineNumber":129,"sourceCode":"\treturn Principal{\n\t\tType: PrincipalEmbedSession,\n\t\tID:   fmt.Sprintf(\"%d:%s:%s\", tenantID, strings.TrimSpace(channelID), strings.TrimSpace(sessionID)),\n\t}\n}\n\n// EmbedVisitorPrincipal identifies one anonymous embed visitor (browser).\nfunc EmbedVisitorPrincipal(tenantID uint64, channelID, visitorID string) Principal {\n\treturn Principal{\n\t\tType: PrincipalEmbedVisitor,\n\t\tID:   fmt.Sprintf(\"%d:%s:%s\", tenantID, strings.TrimSpace(channelID), strings.TrimSpace(visitorID)),\n\t}\n}\n\n// ValidateEmbedVisitorID checks the client-supplied anonymous visitor id.\nfunc ValidateEmbedVisitorID(id string) error {\n\tid = strings.TrimSpace(id)\n\tif id == \"\" {\n\t\treturn fmt.Errorf(\"empty embed visitor id\")\n\t}\n\tif len(id) > 128 {\n\t\treturn fmt.Errorf(\"embed visitor id too long (max 128)\")\n\t}\n\tfor _, r := range id {\n\t\tif r < 0x20 || r == 0x7f {\n\t\t\treturn fmt.Errorf(\"embed visitor id contains invalid characters\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// MCPOAuthPrincipalFromContext resolves the OAuth token principal for ctx.\n// Embed chat sessions map to a per-visitor principal when X-Embed-Visitor is\n// present; otherwise OAuth falls back to the chat session principal.\nfunc MCPOAuthPrincipalFromContext(ctx context.Context) Principal {\n\tp, ok := PrincipalFromContext(ctx)\n\tif !ok {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/types/principal.go#L111-L147","documentation":"ValidateEmbedVisitorID rejects an empty (or whitespace-only) client-supplied anonymous visitor id. The embed session bootstrap (ensureEmbedSession) requires a non-empty visitor id to associate the session with an anonymous user, so it fails fast with this error.","triggerScenarios":"Calling ensureEmbedSession (directly or via the embed endpoint) without supplying a visitor id, or supplying one that is only whitespace, causing TrimSpace to yield \"\".","commonSituations":"Embed frontend not persisting/generating the visitor id cookie or localStorage key before the first API call, a cleared browser storage, or an API client omitting the visitor id header/field entirely.","solutions":["Generate and send a non-empty visitor id (e.g. a UUID) with the embed session request","Check the embed client actually persists/reads the visitor id before calling the API","Trim/verify the value client-side; if empty, generate a fresh id instead of sending a blank string","Inspect the request payload/headers to confirm the visitor id field is populated"],"exampleFix":"// before\nvisitorID := \"\"\nensureEmbedSession(visitorID)\n// after\nvisitorID := existingOrNewUUID()\nif strings.TrimSpace(visitorID) == \"\" { visitorID = uuid.NewString() }\nensureEmbedSession(visitorID)","handlingStrategy":"validation","validationCode":"func hasVisitorID(id string) bool { return strings.TrimSpace(id) != \"\" }\nif !hasVisitorID(visitorID) { visitorID = uuid.NewString() }","typeGuard":"func isNonEmptyTrimmed(s string) bool { return strings.TrimSpace(s) != \"\" }","tryCatchPattern":"if err := ValidateEmbedVisitorID(id); err != nil {\n    if strings.Contains(err.Error(), \"empty embed visitor id\") {\n        id = uuid.NewString() // regenerate and retry\n    }\n}","preventionTips":["Generate the visitor id once and persist it (cookie/localStorage) before any embed calls","Always trim and check the id client-side before sending","Never send user-editable empty placeholders as visitor ids"],"tags":["validation","embed","session","go"],"backgroundTag":"missing-required-argument","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}