{"record":{"id":"01cebc4337948b46","repo":"JanDeDobbeleer/oh-my-posh","slug":"cannot-extract-tfm-from-s-project-file","errorCode":null,"errorMessage":"cannot extract TFM from %s project file","messagePattern":"cannot extract TFM from (.+?) project file","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/segments/project.go","lineNumber":400,"sourceCode":"\t\t\t\ttarget = values[\"TFM\"]\n\t\t\t}\n\t\t}\n\t}\n\n\t// mirror MSBuild's implicit import of Directory.Build.props when the\n\t// project/solution itself does not define a TargetFramework\n\tif target == \"\" {\n\t\tif props, err := n.env.HasParentFilePath(\"Directory.Build.props\", false); err == nil {\n\t\t\tpropsContent := n.env.FileContent(props.Path)\n\t\t\tvalues = regex.FindNamedRegexMatch(tag, propsContent)\n\t\t\tif len(values) != 0 {\n\t\t\t\ttarget = values[\"TFM\"]\n\t\t\t}\n\t\t}\n\t}\n\n\tif target == \"\" {\n\t\tlog.Error(fmt.Errorf(\"cannot extract TFM from %s project file\", name))\n\t}\n\n\treturn &ProjectData{\n\t\tTarget: target,\n\t\tName:   name,\n\t}\n}\n\n// Scans rootEntries and their subdirectories breadth-first, up to maxDepth levels deep.\n// Paths are kept relative to pwd so FileContent resolves them the same way the caller does.\nfunc (n *Project) findProjectFile(rootEntries []fs.DirEntry, maxDepth int) string {\n\tprojectExts := []string{\".csproj\", \".fsproj\", \".vbproj\"}\n\tpwd := n.env.Pwd()\n\n\tvar dirs []string\n\tfor _, entry := range rootEntries {\n\t\tif entry.IsDir() {\n\t\t\tdirs = append(dirs, entry.Name())","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/JanDeDobbeleer/oh-my-posh/blob/0976794618c5ed95de0985dded50de1b4dc914cb/src/segments/project.go#L382-L418","documentation":"When scanning a .NET (dotnet) project file for the project segment, the parser looks for the TargetFrameworkMoniker (TFM) value. If no TFM is found in the project file, it logs 'cannot extract TFM from <file> project file' — notably this is only logged; the function still returns ProjectData with an empty Target.","triggerScenarios":"Parsing an SDK-style csproj/fsproj/vbproj that declares no resolvable TFM (no TargetFramework/TargetFrameworkMoniker property), a multi-targeted project using TargetFrameworks, or a legacy/non-standard project layout whose property names differ.","commonSituations":"Multi-targeting (`<TargetFrameworks>net8.0;net6.0</TargetFrameworks>`) which the simple parser doesn't pick up; project files generated by non-MSBuild tools; solution containing test/utility projects without an explicit TFM.","solutions":["Add an explicit `<TargetFramework>` element to the project file","For multi-targeted projects, pick a single framework or accept the empty Target and rely on the project name display","Check the project file is a standard MSBuild format the parser supports","This is logged-only: verify whether the empty Target actually breaks your template; if not, it can be ignored"],"exampleFix":"<!-- before -->\n<Project><PropertyGroup><TargetFrameworks>net8.0;net6.0</TargetFrameworks></PropertyGroup></Project>\n<!-- after: parser-readable single TFM -->\n<Project><PropertyGroup><TargetFramework>net8.0</TargetFramework></PropertyGroup></Project>","handlingStrategy":"validation","validationCode":"// grep the project file for a TFM before enabling\ncontent, _ := os.ReadFile(\"myapp.csproj\")\nhasTFM := strings.Contains(string(content), \"<TargetFramework>\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare <TargetFramework> in SDK-style projects","Avoid relying on multi-targeting for prompt-driven project info","Keep project files in standard MSBuild format","Remember the message is logged-only; empty Target may be harmless"],"tags":["go","parsing","dotnet","project-file"],"backgroundTag":"missing-config-field","analyzedSha":"0976794618c5ed95de0985dded50de1b4dc914cb","analyzedAt":"2026-08-31T23:41:19.708Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}