{"record":{"id":"49b70063b65505fd","repo":"usememos/memos","slug":"invalid-uid","errorCode":null,"errorMessage":"invalid uid","messagePattern":"invalid uid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/memo.go","lineNumber":111,"sourceCode":"type UpdateMemo struct {\n\tID         int32\n\tUID        *string\n\tCreatedTs  *int64\n\tUpdatedTs  *int64\n\tRowStatus  *RowStatus\n\tContent    *string\n\tVisibility *Visibility\n\tPinned     *bool\n\tPayload    *storepb.MemoPayload\n}\n\ntype DeleteMemo struct {\n\tID int32\n}\n\nfunc (s *Store) CreateMemo(ctx context.Context, create *Memo) (*Memo, error) {\n\tif !base.UIDMatcher.MatchString(create.UID) {\n\t\treturn nil, errors.New(\"invalid uid\")\n\t}\n\treturn s.driver.CreateMemo(ctx, create)\n}\n\nfunc (s *Store) ListMemos(ctx context.Context, find *FindMemo) ([]*Memo, error) {\n\treturn s.driver.ListMemos(ctx, find)\n}\n\nfunc (s *Store) GetMemo(ctx context.Context, find *FindMemo) (*Memo, error) {\n\tlist, err := s.ListMemos(ctx, find)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(list) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tmemo := list[0]","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/store/memo.go#L93-L129","documentation":"Returned by Store.CreateMemo when the supplied memo UID does not match base.UIDMatcher: ^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,34}[a-zA-Z0-9])?$ — 1 to 36 characters, must start and end with a letter or digit, and may contain only letters, digits and dashes in between. UIDs become resource names (memos/<uid>), so the format is enforced before the row reaches any database driver. This is a normal API-level validation error, not a startup failure.","triggerScenarios":"Calling the memo-creation API path that sets a custom uid with an empty string, a uid containing underscores/dots/slashes, a uid longer than 36 characters, or one starting/ending with a dash. Auto-generated UIDs that collide with these rules (rare) would surface the same error.","commonSituations":"Clients importing notes from another system and reusing foreign slugs with underscores; trimming/normalizing loops that produce an empty uid; resource-name parsing that passes 'memos/abc' as the uid instead of 'abc'.","solutions":["Send a uid of 1-36 characters using only [a-zA-Z0-9-], starting and ending with a letter or digit (replace '_' with '-').","If you do not need a custom uid, omit the field and let the server generate one.","If parsing a resource name like \"memos/abc123\", pass only the segment after the slash."],"exampleFix":"// before\nmemo, err := store.CreateMemo(ctx, &store.Memo{ UID: \"my_note_2024!\", Content: &content })\n\n// after\nmemo, err := store.CreateMemo(ctx, &store.Memo{ UID: \"my-note-2024\", Content: &content })","handlingStrategy":"validation","validationCode":"// Go callers: validate before CreateMemo\nvar uidMatcher = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,34}[a-zA-Z0-9])?$`)\nif create.UID != \"\" && !uidMatcher.MatchString(create.UID) {\n    return errors.New(\"uid must be 1-36 chars of [a-zA-Z0-9-], alphanumeric at both ends\")\n}\nmemo, err := s.CreateMemo(ctx, create)","typeGuard":"func isValidMemoUID(uid string) bool {\n    ok := len(uid) >= 1 && len(uid) <= 36\n    if !ok {\n        return false\n    }\n    for i, r := range uid {\n        alnum := (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9')\n        if i == 0 || i == len(uid)-1 {\n            if !alnum {\n                return false\n            }\n        } else if !alnum && r != '-' {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"// In service layer: map store validation errors to InvalidArgument\nmemo, err := s.Store.CreateMemo(ctx, create)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid uid\") {\n        return nil, status.Errorf(codes.InvalidArgument, \"uid must match [a-zA-Z0-9-]{1,36} with alphanumeric ends\")\n    }\n    return nil, status.Errorf(codes.Internal, \"failed to create memo\")\n}","preventionTips":["Let the server generate UIDs unless you truly need stable slugs (e.g. imports).","When importing, sanitize foreign ids: lowercase, replace '_' and '.' with '-', trim dashes, truncate to 36.","Pass the bare uid, not the resource name 'memos/<uid>'."],"tags":["validation","memo","uid","api"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}