{"record":{"id":"c6d4d6b7f44998be","repo":"gocolly/colly","slug":"errnopattern","errorCode":"ErrNoPattern","errorMessage":"No pattern defined in LimitRule","messagePattern":"No pattern defined in LimitRule","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"colly.go","lineNumber":240,"sourceCode":"\t// a domain which is not allowed in AllowedDomains\n\tErrForbiddenDomain = errors.New(\"Forbidden domain\")\n\t// ErrMissingURL is the error type for missing URL errors\n\tErrMissingURL = errors.New(\"Missing URL\")\n\t// ErrMaxDepth is the error type for exceeding max depth\n\tErrMaxDepth = errors.New(\"Max depth limit reached\")\n\t// ErrForbiddenURL is the error thrown if visiting\n\t// a URL which is not allowed by URLFilters\n\tErrForbiddenURL = errors.New(\"ForbiddenURL\")\n\n\t// ErrNoURLFiltersMatch is the error thrown if visiting\n\t// a URL which is not allowed by URLFilters\n\tErrNoURLFiltersMatch = errors.New(\"No URLFilters match\")\n\t// ErrRobotsTxtBlocked is the error type for robots.txt errors\n\tErrRobotsTxtBlocked = errors.New(\"URL blocked by robots.txt\")\n\t// ErrNoCookieJar is the error type for missing cookie jar\n\tErrNoCookieJar = errors.New(\"Cookie jar is not available\")\n\t// ErrNoPattern is the error type for LimitRules without patterns\n\tErrNoPattern = errors.New(\"No pattern defined in LimitRule\")\n\t// ErrEmptyProxyURL is the error type for empty Proxy URL list\n\tErrEmptyProxyURL = errors.New(\"Proxy URL list is empty\")\n\t// ErrAbortedAfterHeaders is the error returned when OnResponseHeaders aborts the transfer.\n\tErrAbortedAfterHeaders = errors.New(\"Aborted after receiving response headers\")\n\t// ErrAbortedBeforeRequest is the error returned when OnResponseHeaders aborts the transfer.\n\tErrAbortedBeforeRequest = errors.New(\"Aborted before Do Request\")\n\t// ErrQueueFull is the error returned when the queue is full\n\tErrQueueFull = errors.New(\"Queue MaxSize reached\")\n\t// ErrMaxRequests is the error returned when exceeding max requests\n\tErrMaxRequests = errors.New(\"Max Requests limit reached\")\n\t// ErrRetryBodyUnseekable is the error when retry with not seekable body\n\tErrRetryBodyUnseekable = errors.New(\"Retry Body Unseekable\")\n)\n\nvar envMap = map[string]func(*Collector, string){\n\t\"ALLOWED_DOMAINS\": func(c *Collector, val string) {\n\t\tc.AllowedDomains = strings.Split(val, \",\")\n\t},","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/gocolly/colly/blob/17d1d6ca92bd32a5651f34256bf7a2855c967f65/colly.go#L222-L258","documentation":"ErrNoPattern is returned by LimitRule.Init() when a LimitRule has no URL pattern defined. Limit rules use regexp patterns to match which URLs a rate limit applies to; a rule without DomainRegexp, Domain, or URLRegexp/Path cannot be compiled, so Init fails and the collector cannot start limiting.","triggerScenarios":"Calling c.LimitRule(&colly.LimitRule{DomainRegexp: \"...\", Delay: ...}) with a rule missing any pattern fields; constructing rules dynamically where the pattern string ends up empty; c.Limit/rules initialization loops where one entry forgot its pattern.","commonSituations":"Building LimitRules from config/JSON where the pattern key is absent or empty; copy-pasting a rule and deleting the Domain/DomainRegexp line; programmatically generating rules for multiple domains where one domain string is blank.","solutions":["Set a pattern on the rule: Domain, DomainRegexp, or URLRegexp must be non-empty","Validate rule config at startup before calling c.LimitRule","Skip empty rules in generated config instead of passing them to LimitRule","Double-check field names — pattern fields are DomainRegexp/DomainGlob/URLRegexp etc., not \"Pattern\""],"exampleFix":"// before\nrule := &colly.LimitRule{Delay: 2 * time.Second, RandomDelay: time.Second}\nerr := c.LimitRule(rule) // ErrNoPattern: no pattern defined\n// after\nrule := &colly.LimitRule{DomainRegexp: \"example\\.com\", Delay: 2 * time.Second, RandomDelay: time.Second}\nerr := c.LimitRule(rule)","handlingStrategy":"validation","validationCode":"for _, r := range rules {\n    if r.Domain == \"\" && r.DomainRegexp == \"\" && r.DomainGlob == \"\" && r.URLRegexp == \"\" {\n        return fmt.Errorf(\"limit rule %+v has no pattern\", r)\n    }\n}\nfor _, r := range rules {\n    if err := c.LimitRule(r); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"if err := c.LimitRule(rule); err != nil {\n    if errors.Is(err, colly.ErrNoPattern) {\n        return fmt.Errorf(\"rule %v missing Domain/DomainRegexp/URLRegexp: %w\", rule, err)\n    }\n    return err\n}","preventionTips":["Validate rule config (patterns non-empty) before LimitRule calls","Keep limit rules in reviewed config files, not ad-hoc literals","Skip or reject empty generated rules instead of passing them through"],"tags":["colly","scraping","rate-limit","configuration","go"],"backgroundTag":"missing-required-config-field","analyzedSha":"17d1d6ca92bd32a5651f34256bf7a2855c967f65","analyzedAt":"2026-08-30T21:32:31.579Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}