{"record":{"id":"212748371b9ec12e","repo":"micro/go-micro","slug":"joined-load-errors","errorCode":null,"errorMessage":"<joined load errors>","messagePattern":"<joined load errors>","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/loader/memory/memory.go","lineNumber":354,"sourceCode":"\t\t\tcontinue\n\t\t}\n\t\tm.Lock()\n\t\tm.sources = append(m.sources, source)\n\t\tm.sets = append(m.sets, set)\n\t\tidx := len(m.sets) - 1\n\t\tm.Unlock()\n\t\tif !m.opts.WithWatcherDisabled {\n\t\t\tgo m.watch(idx, source)\n\t\t}\n\t}\n\n\tif err := m.reload(); err != nil {\n\t\tgerrors = append(gerrors, err.Error())\n\t}\n\n\t// Return errors\n\tif len(gerrors) != 0 {\n\t\treturn errors.New(strings.Join(gerrors, \"\\n\"))\n\t}\n\treturn nil\n}\n\nfunc (m *memory) Watch(path ...string) (loader.Watcher, error) {\n\tif m.opts.WithWatcherDisabled {\n\t\treturn nil, errors.New(\"watcher is disabled\")\n\t}\n\n\tvalue, err := m.Get(path...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tm.Lock()\n\n\tw := &watcher{\n\t\texit:    make(chan bool),","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/config/loader/memory/memory.go#L336-L372","documentation":"The memory loader's Load iterates each source, calling its Read and accumulating failures, then calls m.reload() to rebuild the merged value set; any reload error is also appended. If any errors were collected they are joined with newlines into a single error and returned. The message text is the concatenation of all per-source/reload errors, so the root causes are inside the joined string.","triggerScenarios":"loader.Load(sources...) where at least one source.Read fails (file missing, invalid format, connection error) or m.reload() fails after merging (e.g. one source's changeset cannot be applied), producing a multi-line joined error.","commonSituations":"Pointing config at a file/env/etcd source that doesn't exist or is unreachable in a new environment; a YAML/JSON file with a syntax error among otherwise-valid sources; secrets or permissions changes after a deploy causing one source to fail while others succeed.","solutions":["Read each line of the returned joined error to identify which source(s) failed, then fix that source (path, address, credentials, format).","Validate source files/connections before deployment (parse the JSON/YAML, ping the config server).","Call Load at startup and fail fast instead of continuing with a partially loaded config.","If a source is optional, load it separately and tolerate its failure rather than passing it into the main Load call."],"exampleFix":"// before\nloader.Load(fileSrc, etcdSrc) // errors ignored\n// after\nif err := loader.Load(fileSrc, etcdSrc); err != nil {\n    log.Fatalf(\"config load failed: %v\", err) // shows each failing source\n}","handlingStrategy":"try-catch","validationCode":"for _, s := range sources {\n    if _, err := s.Read(); err != nil {\n        return fmt.Errorf(\"source %s unreadable before load: %w\", s.String(), err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := loader.Load(sources...); err != nil {\n    for _, line := range strings.Split(err.Error(), \"\\n\") {\n        log.Printf(\"config source error: %s\", line)\n    }\n    return err\n}","preventionTips":["Fail fast at startup when Load returns an error.","Validate config files (parse them) in CI before deploy.","Check connectivity/permissions of remote sources (etcd, consul) pre-deploy.","Load optional sources separately so one failure doesn't block the rest."],"tags":["config","loader","go","aggregated-errors","sources"],"backgroundTag":"config-load-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}