Repository: gohugoio/hugo (language: go)

Issue:
defaultContentLanguage not validated
site config

```
defaultContentLanguage = 'en'   # does not match any of the defined languages

[languages.de]
weight = 1

[languages.fr]
weight = 2
```

#### v0.111.3

```text
$ hugo

Error: site config value "en" for defaultContentLanguage does not match any language definition
```

#### v0.112.5

```text
$ hugo
```

No error, and the published site is wrong:

```text
public/
├── de/
│   └── index.html
├── en/
│   └── index.html
├── fr/
│   ├── posts/
│   │   ├── post-1/
│   │   │   └── index.html
│   │   └── index.html
│   └── index.html
└── favicon.ico
````




Discussion / hints:

Fix patch:
diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go
index ade7ea1be72..abb95554658 100644
--- a/config/allconfig/allconfig.go
+++ b/config/allconfig/allconfig.go
@@ -729,8 +729,8 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
 					isMultiHost = true
 				}
 				mergedConfig.Set(kk, vv)
-				if cfg.IsSet(kk) {
-					rootv := cfg.Get(kk)
+				rootv := cfg.Get(kk)
+				if rootv != nil && cfg.IsSet(kk) {
 					// This overrides a root key and potentially needs a merge.
 					if !reflect.DeepEqual(rootv, vv) {
 						switch vvv := vv.(type) {
diff --git a/config/allconfig/alldecoders.go b/config/allconfig/alldecoders.go
index c8944bd2d1f..b45bd1e11be 100644
--- a/config/allconfig/alldecoders.go
+++ b/config/allconfig/alldecoders.go
@@ -60,7 +60,14 @@ var allDecoderSetups = map[string]decodeWeight{
 		key:    "",
 		weight: -100, // Always first.
 		decode: func(d decodeWeight, p decodeConfig) error {
-			return mapstructure.WeakDecode(p.p.Get(""), &p.c.RootConfig)
+			if err := mapstructure.WeakDecode(p.p.Get(""), &p.c.RootConfig); err != nil {
+				return err
+			}
+
+			// This need to match with Lang which is always lower case.
+			p.c.RootConfig.DefaultContentLanguage = strings.ToLower(p.c.RootConfig.DefaultContentLanguage)
+
+			return nil
 		},
 	},
 	"imaging": {
@@ -245,12 +252,17 @@ var allDecoderSetups = map[string]decodeWeight{
 			if len(m) == 1 {
 				// In v0.112.4 we moved this to the language config, but it's very commmon for mono language sites to have this at the top level.
 				var first maps.Params
+				var ok bool
 				for _, v := range m {
-					first = v.(maps.Params)
-					break
+					first, ok = v.(maps.Params)
+					if ok {
+						break
+					}
 				}
-				if _, found := first["languagecode"]; !found {
-					first["languagecode"] = p.p.GetString("languagecode")
+				if first != nil {
+					if _, found := first["languagecode"]; !found {
+						first["languagecode"] = p.p.GetString("languagecode")
+					}
 				}
 			}
 			p.c.Languages, err = langs.DecodeConfig(m)
@@ -258,6 +270,18 @@ var allDecoderSetups = map[string]decodeWeight{
 				return err
 			}
 
+			// Validate defaultContentLanguage.
+			var found bool
+			for lang := range p.c.Languages {
+				if lang == p.c.DefaultContentLanguage {
+					found = true
+					break
+				}
+			}
+			if !found {
+				return fmt.Errorf("config value %q for defaultContentLanguage does not match any language definition", p.c.DefaultContentLanguage)
+			}
+
 			return nil
 		},
 	},
diff --git a/langs/config.go b/langs/config.go
index 15c0bedbc42..f60ea94a4dd 100644
--- a/langs/config.go
+++ b/langs/config.go
@@ -14,6 +14,8 @@
 package langs
 
 import (
+	"errors"
+
 	"github.com/gohugoio/hugo/common/maps"
 	"github.com/mitchellh/mapstructure"
 )
@@ -46,5 +48,8 @@ func DecodeConfig(m map[string]any) (map[string]LanguageConfig, error) {
 	if err := mapstructure.WeakDecode(m, &langs); err != nil {
 		return nil, err
 	}
+	if len(langs) == 0 {
+		return nil, errors.New("no languages configured")
+	}
 	return langs, nil
 }


Test patch:
diff --git a/hugolib/config_test.go b/hugolib/config_test.go
index a8e3b8f2caa..814be667f06 100644
--- a/hugolib/config_test.go
+++ b/hugolib/config_test.go
@@ -1066,3 +1066,88 @@ LanguageCode: {{ .Site.LanguageCode }}|{{ site.Language.LanguageCode }}|
 	b.AssertFileContent("public/index.html", "LanguageCode: en-US|en-US|")
 
 }
+
+func TestConfigMiscPanics(t *testing.T) {
+	t.Parallel()
+
+	// Issue 11047,
+	t.Run("empty params", func(t *testing.T) {
+
+		files := `
+-- hugo.yaml --
+params:
+-- layouts/index.html --
+Foo: {{ site.Params.foo }}|
+	
+		
+	`
+		b := NewIntegrationTestBuilder(
+			IntegrationTestConfig{
+				T:           t,
+				TxtarString: files,
+			},
+		).Build()
+
+		b.AssertFileContent("public/index.html", "Foo: |")
+	})
+
+	// Issue 11046
+	t.Run("invalid language setup", func(t *testing.T) {
+
+		files := `
+-- hugo.toml --
+baseURL = "https://example.org"
+languageCode = "en-us"
+title = "Blog of me"
+defaultContentLanguage = "en"
+
+[languages]
+	[en]
+	lang = "en"
+	languageName = "English"
+	weight = 1
+-- layouts/index.html --
+Foo: {{ site.Params.foo }}|
+	
+		
+	`
+		b, err := NewIntegrationTestBuilder(
+			IntegrationTestConfig{
+				T:           t,
+				TxtarString: files,
+			},
+		).BuildE()
+
+		b.Assert(err, qt.IsNotNil)
+		b.Assert(err.Error(), qt.Contains, "no languages")
+	})
+
+	// Issue 11044
+	t.Run("invalid defaultContentLanguage", func(t *testing.T) {
+
+		files := `
+-- hugo.toml --
+baseURL = "https://example.org"
+defaultContentLanguage = "sv"
+
+[languages]
+[languages.en]
+languageCode = "en"
+languageName = "English"
+weight = 1
+
+	
+		
+	`
+		b, err := NewIntegrationTestBuilder(
+			IntegrationTestConfig{
+				T:           t,
+				TxtarString: files,
+			},
+		).BuildE()
+
+		b.Assert(err, qt.IsNotNil)
+		b.Assert(err.Error(), qt.Contains, "defaultContentLanguage does not match any language definition")
+	})
+
+}