JanDeDobbeleer/oh-my-posh · warning
cannot extract TFM from %s project file
Error message
cannot extract TFM from %s project file
What it means
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.
Source
Thrown at src/segments/project.go:400
target = values["TFM"]
}
}
}
// mirror MSBuild's implicit import of Directory.Build.props when the
// project/solution itself does not define a TargetFramework
if target == "" {
if props, err := n.env.HasParentFilePath("Directory.Build.props", false); err == nil {
propsContent := n.env.FileContent(props.Path)
values = regex.FindNamedRegexMatch(tag, propsContent)
if len(values) != 0 {
target = values["TFM"]
}
}
}
if target == "" {
log.Error(fmt.Errorf("cannot extract TFM from %s project file", name))
}
return &ProjectData{
Target: target,
Name: name,
}
}
// Scans rootEntries and their subdirectories breadth-first, up to maxDepth levels deep.
// Paths are kept relative to pwd so FileContent resolves them the same way the caller does.
func (n *Project) findProjectFile(rootEntries []fs.DirEntry, maxDepth int) string {
projectExts := []string{".csproj", ".fsproj", ".vbproj"}
pwd := n.env.Pwd()
var dirs []string
for _, entry := range rootEntries {
if entry.IsDir() {
dirs = append(dirs, entry.Name())View on GitHub (pinned to 0976794618)
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
Example fix
<!-- before --> <Project><PropertyGroup><TargetFrameworks>net8.0;net6.0</TargetFrameworks></PropertyGroup></Project> <!-- after: parser-readable single TFM --> <Project><PropertyGroup><TargetFramework>net8.0</TargetFramework></PropertyGroup></Project>
Defensive patterns
Strategy: validation
Validate before calling
// grep the project file for a TFM before enabling
content, _ := os.ReadFile("myapp.csproj")
hasTFM := strings.Contains(string(content), "<TargetFramework>") Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- err parsing info from %s with %s
- gitstatus: truncated delta insert
- gitstatus: delta target size mismatch
- unclosed section:
- key-value delimiter not found:
AI-assisted analysis of JanDeDobbeleer/oh-my-posh@0976794618 (2026-08-31).
Data as JSON: /api/errors/01cebc4337948b46.
Report an issue: GitHub.