{"record":{"id":"76dd96184b96116a","repo":"Tencent/WeKnora","slug":"invite-code-has-expired","errorCode":null,"errorMessage":"invite code has expired","messagePattern":"invite code has expired","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/repository/organization.go","lineNumber":18,"sourceCode":"package repository\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/Tencent/WeKnora/internal/types\"\n\t\"github.com/Tencent/WeKnora/internal/types/interfaces\"\n\t\"gorm.io/gorm\"\n)\n\nvar (\n\tErrOrganizationNotFound   = errors.New(\"organization not found\")\n\tErrOrgMemberNotFound      = errors.New(\"organization member not found\")\n\tErrOrgMemberAlreadyExists = errors.New(\"member already exists in organization\")\n\tErrInviteCodeNotFound     = errors.New(\"invite code not found\")\n\tErrInviteCodeExpired      = errors.New(\"invite code has expired\")\n)\n\n// organizationRepository implements OrganizationRepository.\n//\n// Plan 3 of #1303 lifts membership from per-user to per-tenant (see\n// migration 000045). All \"member\" methods on this repo now operate on\n// the (org, tenant) tuple; the underlying table is\n// organization_tenant_members.\ntype organizationRepository struct {\n\tdb *gorm.DB\n}\n\n// NewOrganizationRepository creates a new organization repository\nfunc NewOrganizationRepository(db *gorm.DB) interfaces.OrganizationRepository {\n\treturn &organizationRepository{db: db}\n}\n\n// Create creates a new organization","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/repository/organization.go#L1-L36","documentation":"The SQL validator parsed the SELECT and finished walking all clauses, but its tablesInQuery map (populated only by RangeVar table references in the FROM clause) ended up empty. This library requires every validated query to read from at least one explicitly allowed table, so table-less SELECTs are rejected as a guard against queries that only evaluate expressions or functions.","triggerScenarios":"Passing a SELECT with no FROM clause (e.g. `SELECT 1`, `SELECT version()`, `SELECT now()`), or a SELECT whose FROM items were all rejected earlier (though those usually error first), through the SQL injection validator's validateSelectStmt.","commonSituations":"Health-check or ping queries like `SELECT 1` used by connection pools ORMs and probes; scalar expression evaluation via SELECT; dynamically generated queries where the FROM clause was accidentally omitted or template logic dropped it.","solutions":["Add a FROM clause referencing a real (public-schema) table, e.g. `SELECT 1` becomes `SELECT 1 FROM my_table LIMIT 1` if a table read is intended.","If the query is only a connectivity/liveness probe, bypass the validator and use the driver's native ping instead of routing it through SQL validation.","If dynamic SQL generation dropped the FROM clause, fix the query builder/template so the table reference is always emitted."],"exampleFix":"// before\nSELECT 1;\n\n// after\nSELECT 1 FROM users LIMIT 1;","handlingStrategy":"validation","validationCode":"func hasFromClause(sql string) bool {\n\treturn regexp.MustCompile(`(?i)\\bfrom\\b`).MatchString(sql)\n}\n// skip validation path for pure liveness probes like \"SELECT 1\"","typeGuard":null,"tryCatchPattern":"err := validator.ValidateQuery(sql)\nif err != nil && strings.Contains(err.Error(), \"no valid table found\") {\n\t// route to a non-validated probe path or fix the query to include FROM\n}","preventionTips":["Never use SELECT-expression-only queries through the validator; use a driver ping for liveness checks.","Ensure query builders always emit a FROM clause referencing a public table.","Add a pre-check that a FROM token with a real table name exists before calling the validator."],"tags":["sql","validation","query-structure"],"backgroundTag":"sql-validation-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}