OneDrive "Files On-Demand" and Business Apps — The Assumptions Placeholders Break and How to Deal with Them
· Go Komura · OneDrive, Files On-Demand, KFM, Windows, Business Apps, Cloud Storage, File System, Troubleshooting, Information Systems
“A business app cannot read a CSV I saved on the desktop.” “An import that used to work fails with ‘file not found’ after a PC replacement.” “Explorer shows the file, but opening it from the app errors.” — Over the last few years, this kind of consultation from customers has become a staple.
When you investigate, the cause is often not an app bug but OneDrive’s “automatic backup of Desktop and Documents” (Known Folder Move, KFM) and “Files On-Demand”. The real Desktop has moved to C:\Users\<name>\OneDrive\Desktop, and some of the files you see there are “placeholders” with no local content. Users and IT keep using the PC without noticing this change.
In other words, the implicit assumption of a business app that “the file is on the local disk” has, without anyone deciding it, been replaced by the assumption that “the file is in the cloud, and locally there is only the appearance”. Aimed at IT staff in small and medium businesses and at Windows app developers, this article organizes, from Microsoft Learn primary sources, how placeholders work, how to judge state from file attributes, the typical pitfalls a business app steps in, what both the development side and the IT side can do, and a triage procedure for when you are asked “the file will not open”.
flowchart TB
accTitle: Replacement of a business app's implicit assumption
accDescr: The implicit assumption of a business app that the file is on the local disk has, without anyone deciding it, been replaced by the assumption that the real content is in the cloud and locally there is only the appearance
before["The traditional implicit assumption"] --> b1["Real content on the local disk"]
after["The replaced assumption"] --> a1["The real content is in the cloud"]
a1 --> a2["Locally there is only the appearance"]
a2 -.-> note["A placeholder"]
Figure 1: The assumption that “the real content is local” has, without anyone deciding it, been replaced by “the real content is in the cloud; locally there is only the appearance”.
1. The Bottom Line First
- Desktop, Documents, and Pictures may have been moved under
C:\Users\<name>\OneDrive\by KFM. It tends to be turned on during the initial setup of a new PC, and an organization can also apply it in bulk by policy. An app that assumes a fixed path breaks here.1 - Files On-Demand is on by default in the current sync app. Files created on another device or on the Web appear as “online-only” placeholders with no local content.23
- The real identity of a placeholder is a reparse point managed by the Cloud Files API (the cldflt.sys minifilter). It looks like an ordinary file both to Explorer and to the file APIs, and opening it downloads (hydrates) automatically.4
- State can be judged from file attributes. FILE_ATTRIBUTE_OFFLINE, RECALL_ON_DATA_ACCESS, PINNED, UNPINNED, and the like are the markers, and the attrib command shows them as the letters O, P, and U. Checking attributes alone does not cause a download.567
- Typical accidents in a business app are a combination of “will not open”, “slow”, “mis-judged attributes”, “a storm of watch events”, and “conflict with sync”. Offline or with OneDrive stopped, hydration fails, and a batch process induces a download of every file.48
- The app-side response is to “respect placeholders”. The basics are judging from attributes at enumeration time and not opening carelessly, using FILE_FLAG_OPEN_NO_RECALL if needed, and not putting the data folder under OneDrive.910
- The IT-side response is “operating with pins” and “control by policy”. Guarantee real content for business folders with “Always keep on this device”, and configure KFM and Files On-Demand on purpose with Group Policy / Intune. Do not forget that Storage Sense can also “return unused files to online-only”.1112
In one sentence: “a file visible in Explorer” and “a file that has real content on the local disk” are no longer the same thing.
2. What Is Happening — KFM and Files On-Demand
2.1. The Desktop May No Longer Be C:\Users\<name>\Desktop
The OneDrive sync app has a feature called Known Folder Move (KFM). On the settings screen it is shown as “Backup”, “Back up important folders”, and the like; when it is on, the real Desktop, Documents, and Pictures are moved (redirected) under the OneDrive folder.1
| Place the user sees | Real path before KFM | Real path after KFM |
|---|---|---|
| Desktop | C:\Users\taro\Desktop |
C:\Users\taro\OneDrive\Desktop |
| Documents | C:\Users\taro\Documents |
C:\Users\taro\OneDrive\Documents |
| Pictures | C:\Users\taro\Pictures |
C:\Users\taro\OneDrive\Pictures |
On the initial setup (OOBE) of a new PC, signing in with a Microsoft account or a work account widely presents folder backup as the default proposal, and proceeding as-is turns it on. An organization can also apply it in bulk without asking the user anything, with the “Silently move Windows known folders to OneDrive” policy (KFMSilentOptIn).111
flowchart TB
accTitle: Two paths by which KFM is turned on
accDescr: Signing in with an account during the initial setup of a new PC presents folder backup as the default proposal and proceeding as-is turns it on; in an organization the KFMSilentOptIn policy applies it in bulk without asking the user
oobe["Initial setup of a new PC"] --> signin["Sign in with an account"]
signin --> prompt["Backup is proposed by default"]
prompt --> on1["Proceeding as-is turns it on"]
org["Organization policy"] --> silent["KFMSilentOptIn"]
silent --> on2["Applied in bulk without asking the user"]
on1 --> kfm["KFM on"]
on2 --> kfm
Figure 2: KFM is turned on without anyone noticing, either by the default proposal at initial setup or by the organization’s silent-apply policy.
The awkward part is that the appearance in Explorer barely changes. The shell known-folder APIs (SHGetKnownFolderPath and .NET’s Environment.GetFolderPath) return the correct post-move path, so a well-behaved app keeps working. What breaks is an app that embeds a fixed path such as C:\Users\%USERNAME%\Desktop in a settings file or in code. The typical pattern of an import failing with “file not found” after a PC replacement is this.
flowchart TB
accTitle: How an app's path resolution behaves after KFM
accDescr: After KFM moves the real Desktop and similar folders under OneDrive, an app that uses the known-folder APIs keeps working with the correct post-move path, but an app that embeds a fixed path fails with file not found
kfm["KFM turned on"] --> move["The real Desktop and similar folders move under OneDrive"]
move --> how{"How does the app resolve the path?"}
how -->|Known-folder APIs| ok["Gets the correct post-move path and keeps working"]
how -->|A hardcoded fixed path| ng["File not found"]
Figure 3: After KFM, an app that uses the known-folder APIs keeps working, but an app that hardcodes a fixed path breaks here.
2.2. Files On-Demand — Visible, but No Real Content
The other lead is Files On-Demand. In an environment where it is on, every file on OneDrive is visible in Explorer, but the contents are not downloaded until the file is opened. This feature is on by default in the current sync app, and Microsoft also recommends leaving it on.23
State can be told from the status icons in Explorer.13
| Icon | State | Local content |
|---|---|---|
| Cloud mark | Online-only | None (placeholder only) |
| Check on a white background | Locally available | Present (but can later be freed automatically) |
| White check on a green background | Always keep on this device (pinned) | Present (outside automatic free-up) |
The important one here is the middle state. A file that has been opened once and now has local content can go back to online-only through the user’s “Free up space” action or through Storage Sense, discussed later. That is one cause of a hard-to-reproduce failure of the “it worked last month” kind.312
stateDiagram-v2
accTitle: The three Files On-Demand states and the transitions
accDescr: An online-only file becomes locally available when opened, but a Free up space action or Storage Sense can return it to online-only, and only a pinned file is outside automatic free-up
s1: Online-only (cloud mark)
s2: Locally available
s3: Pinned (Always keep on this device)
s1 --> s2: Open (hydration)
s2 --> s1: Free up space
s2 --> s1: Storage Sense
s1 --> s3: Always keep on this device
s2 --> s3: Always keep on this device
s3 --> s2: Unpin
Figure 4: The three Files On-Demand states. “Locally available” can automatically return to online-only; a pin is outside that.
3. The Real Identity of a Placeholder — The Cloud Files API and Reparse Points
Files On-Demand is implemented on top of an OS mechanism introduced in Windows 10 version 1709, the Cloud Files API. The file-system-side working unit is a file-system minifilter named cldflt.sys (service name CldFlt, “Windows Cloud Files Filter Driver”), and OneDrive is one “sync provider” that uses this API.47
A placeholder is technically a reparse point. On the file system only metadata such as the file name, size, and timestamps exists (about 1KB); there is no content data. When an app opens the file and reads, the minifilter detects the request, tells the sync provider to transfer the data, waits for the download to finish, and then the read proceeds. This fetch is called hydration; throwing away the local content and returning to a placeholder is called dehydration.4
sequenceDiagram
accTitle: Hydration when a placeholder is opened
accDescr: When an app opens a placeholder and reads, the cldflt.sys minifilter detects the request, tells the sync provider to transfer the data, waits for the download to finish, and then the read proceeds
participant app as Business app
participant flt as cldflt.sys minifilter
participant sync as Sync provider
app->>flt: Open and read request
flt->>sync: Instruct a data transfer
sync-->>flt: Download complete
flt-->>app: The read proceeds
Figure 5: A placeholder read proceeds after the minifilter has the sync provider fetch the data.
Hearing “reparse point” makes you worry about compatibility with existing code that “treats a reparse point specially if it detects one”, but for compatibility the Cloud Files API hides the fact that it is a reparse point from everyone except the sync engine and processes under %systemroot%. From an ordinary app it looks like “an ordinary file that is just a bit slow to open”. That thorough transparency is, at the same time as being convenient, also the reason “the app has its assumptions broken without noticing”.4 The mechanism of reparse points themselves is explained in “NTFS Internals”.
flowchart TB
accTitle: Hiding the reparse point, and the difference in how it looks
accDescr: The real identity of a placeholder is a reparse point, but the Cloud Files API hides that from processes other than the sync engine, so from an ordinary app it looks like an ordinary file that is just a bit slow to open
ph["Placeholder (reparse point)"] --> who{"Which process opened it?"}
who -->|The sync engine and similar| raw["Visible as a reparse point"]
who -->|Any other app| plain["Looks like an ordinary file"]
plain -.-> note["Looks only a bit slow to open"]
Figure 6: The fact that it is a reparse point is hidden from everyone except the sync engine, and to an ordinary app it looks like an ordinary file.
In Explorer properties, a placeholder has the characteristic appearance that “Size” shows the original size, while “Size on disk” is almost 0. The assumption that “it has a size, so it must have real content” does not hold here.
flowchart TB
accTitle: How a placeholder looks in properties
accDescr: In Explorer properties a placeholder shows the original size as Size while Size on disk is almost 0, so the assumption that it has a size and therefore must have real content does not hold
prop["Placeholder properties"] --> size["Size is the original size"]
prop --> disk["Size on disk is almost 0"]
size -.-> trap["The assumption that there must be real content"]
disk -.-> truth["There is no local content"]
Figure 7: A placeholder shows the original size as “Size” while “Size on disk” is almost 0.
4. File Attributes Tell You the State
Placeholder state is published as ordinary file attributes. The main ones are as follows.5
| Attribute | Value | Meaning |
|---|---|---|
| FILE_ATTRIBUTE_OFFLINE | 0x00001000 | The data is not immediately available (the traditional attribute for hierarchical storage management) |
| FILE_ATTRIBUTE_RECALL_ON_OPEN | 0x00040000 | There is no physical local content. Appears only in directory-enumeration results |
| FILE_ATTRIBUTE_PINNED | 0x00080000 | The user intends to “always keep it local” (pinned) |
| FILE_ATTRIBUTE_UNPINNED | 0x00100000 | Local content need not be kept (the intent to make it online-only) |
| FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS | 0x00400000 | Some or all of the contents are not local. Reading causes a fetch from remote |
The command-prompt attrib command can display and set these as a single letter. O is the offline attribute, P is pinned, U is unpinned.6 The correspondence with OneDrive Files On-Demand state is organized in Microsoft’s documentation as follows.7
| Files On-Demand state | Attributes | Command to set |
|---|---|---|
| Always available (pinned) | Pinned (P is displayed) | attrib +p <path> |
| Locally available | Neither P nor U | attrib -p <path> |
| Online-only | Unpinned (U is displayed) | attrib +u <path> |
One caveat. Switching state has an order. When you want an online-only (U) file to become “locally available”, running -p alone leaves U set and the real content is not fetched. Microsoft’s documentation also shows the procedure of first doing +p (always available) to download the real content and then -p.7 In a script that must switch an existing state reliably, it is safer to clear the opposite attribute at the same time, as in attrib +p -u.
flowchart TB
accTitle: The order of switching from online-only to locally available
accDescr: Running attrib -p alone on an online-only file leaves the U attribute and the real content is not fetched; you need the procedure of first downloading the real content with attrib +p and then -p
u["Online-only (U)"] -->|attrib -p only| stay["Stays U; the real content is not fetched"]
u -->|attrib +p| pin["Pinned (download the real content)"]
pin -->|attrib -p| local["Locally available"]
Figure 8: Switching from online-only needs the order of first fetching the real content with +p and then -p.
An example of judging in PowerShell. Looking at attributes alone does not cause hydration, so you can use it with confidence for investigation and bulk checks.
function Test-CloudPlaceholder {
param([Parameter(Mandatory)][string]$Path)
$value = [int](Get-Item -LiteralPath $Path -Force).Attributes
[pscustomobject]@{
Path = $Path
Offline = ($value -band 0x00001000) -ne 0 # FILE_ATTRIBUTE_OFFLINE
RecallOnDataAccess = ($value -band 0x00400000) -ne 0 # Not all of the contents are local
Pinned = ($value -band 0x00080000) -ne 0 # Always keep on this device
Unpinned = ($value -band 0x00100000) -ne 0 # Online-only
}
}
# Bulk-check CSVs under the Documents folder (the contents are not downloaded).
# Resolve the path with the known-folder API. Hardcoding the display name
# "Documents" can become a nonexistent path depending on the real folder name
# (Documents vs. a localized name) and the KFM configuration
Get-ChildItem ([Environment]::GetFolderPath('MyDocuments')) -Recurse -Filter *.csv |
ForEach-Object { Test-CloudPlaceholder $_.FullName } |
Where-Object RecallOnDataAccess |
Format-Table -AutoSize
The cast to [int] is because .NET’s FileAttributes enumeration does not define names such as RECALL_ON_DATA_ACCESS. Bitwise operations on the numeric value can judge without trouble.
5. Pitfalls a Business App Steps In
This is the main subject. Placeholder transparency is convenient most of the time, but combined with a typical business-app processing pattern it surfaces in the following six shapes.
5.1. Opening Automatically Starts a Download — “Will Not Open” Offline
Opening an online-only file starts hydration on the spot. Online, with a small file, it is so fast you do not notice, but when OneDrive is stopped, signed out, or paused, when the network is unhealthy, or when the file is large, it becomes “a file that exists but will not open”. The error can come back as a cloud-file-family code such as ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING (0x8007016A, “The cloud file provider is not running”), or it can be observed as a timeout on the app side.8
A further trap is that an existence check equivalent to File.Exists(), and getting attributes or size, succeed. You get an error pattern that the local-disk intuition cannot explain: “the existence check passed, but the read failed”.
flowchart TB
accTitle: Branches when accessing an online-only file
accDescr: An existence check and getting attributes and size succeed, but reading the contents starts hydration; if OneDrive is running and the network is healthy you can read after the download, otherwise you fail with an error such as 0x8007016A or a timeout
check["Existence check, or getting attributes or size"] --> ok1["Succeeds"]
open["Reading the contents"] --> hyd["Hydration starts"]
hyd --> cond{"OneDrive running and the network healthy?"}
cond -->|Yes| read["Readable after the download"]
cond -->|No| err["An error such as 0x8007016A, or a timeout"]
Figure 9: An existence check can succeed while a read fails. Success or failure depends on whether OneDrive is running and on the network.
5.2. A Batch Process Induces a Download of Every File
Aim a batch that reads every file in a folder, a hash computation, a full-text search, or a homegrown backup at a tree under OneDrive and hydration of every file you touch is induced. For a folder of several GB, the process becomes abnormally slow, the download also fills the disk, and on a low-capacity PC the lack of free space invites a different failure. The capacity Files On-Demand was supposed to save disappears in a single full scan.
Also, if an app causes hydration without an explicit user action, Windows can show a toast and give the user a choice to block. Once blocked, that app keeps failing downloads thereafter (you can lift it with “Automatic file downloads” in Settings). That is one cause of “the import fails only on a particular PC”.4
flowchart TB
accTitle: How a batch process induces a download of every file
accDescr: A batch under OneDrive induces hydration of every file it touches, causing processing delay and disk pressure, and if the user blocks on the toast, downloads keep failing thereafter
scan["A batch under OneDrive"] --> touch["Hydrate every file touched"]
touch --> cost["Processing delay and disk pressure"]
touch --> toast["A toast can appear"]
toast --> block{"Did the user block?"}
block -->|Yes| fail["Downloads keep failing thereafter"]
block -->|No| cont["The download continues"]
Figure 10: A batch induces hydration of every file, and if it is blocked on the toast, failures continue thereafter.
5.3. Misbehavior of Code That Does Not Expect the Attributes
Code that does not know FILE_ATTRIBUTE_OFFLINE or RECALL_ON_DATA_ACCESS misbehaves in unexpected places.
- Attributes are tested for exact equality (
attributes == FileAttributes.Archiveand the like), so a placeholder is excluded or treated as an error as an “unexpected file” - An exclusion decision in a backup or sync tool interprets the OFFLINE attribute as “already staged to tape” and skips (or, conversely, fetches every file it should have excluded)
- A read-only check or an archive-bit operation breaks the attribute combination
flowchart TB
accTitle: Misbehavior patterns of code that does not expect the attributes
accDescr: Code that does not know placeholder attributes misbehaves as exclusion or error handling from an exact-equality attribute test, skip or a full fetch from a misinterpretation of OFFLINE, or breaking the attribute combination
code["Code that does not expect the attributes"] --> m1["Exact-equality test"]
code --> m2["Misinterprets OFFLINE"]
code --> m3["An attribute operation breaks the combination"]
m1 --> r1["Excluded or errored as unexpected"]
m2 --> r2["Skip, or a full fetch"]
Figure 11: Code that does not know OFFLINE or the RECALL-family attributes misbehaves as exclusion, a wrong skip, or attribute destruction.
Microsoft’s guidance for minifilter developers states plainly that you should not issue a careless read or write to a file that has RECALL_ON_DATA_ACCESS. The document is aimed at kernel drivers, but the principle that “touching the contents of a file with this attribute = a fetch cost occurs” applies as-is to a user-mode app.10
5.4. Interaction Between FileSystemWatcher and Sync
Watch a folder under OneDrive with FileSystemWatcher and you get not only user actions but also a large number of events from the sync app’s activity. Every time a change on another device is synced, and every time hydration or dehydration changes attributes or size, a Changed event can fire. Further, a design that writes the result of a watch-and-import back into the same folder becomes a “storm of change notifications” in a loop of write → upload → attribute update → another event. Thinning events and designing a real-content check are as covered in “A Practical Guide to FileSystemWatcher”, but under OneDrive the need for that is one step higher.
flowchart TB
accTitle: A change-notification loop from watching and writing back
accDescr: If a watching app that received a change event writes the import result back to the same folder, the sync app's upload and attribute update fire another event, and it becomes a loop — a storm of change notifications
ev["Change event"] --> proc["The watching app imports"]
proc --> write["Write back to the same folder"]
write --> up["The sync app uploads"]
up --> attr["Attributes or size are updated"]
attr --> ev
sync["Sync of a change from another device"] -.-> ev
Figure 12: Writing the import result back to the same folder becomes a loop in which the sync app’s activity produces another event.
5.5. Sync Conflicts During an Exclusive Lock, and “Copy” Files
While a business app has a file open with an exclusive lock, the sync app can neither upload nor update that file. Putting a long-held-lock app (an Access .accdb, a data file in a homegrown format, a log file, and the like) under OneDrive makes sync errors the normal state. Conversely, when the same file is edited on several PCs, the sync app tries to keep both editions and produces a duplicate file with a PC name or a conflict copy such as “— copy”. An import that assumes “one folder, one file” misbehaves on this duplicate. For the basics of lock design, see “Mutual Exclusion Fundamentals for File-Based Integration”.
flowchart TB
accTitle: Sync problems caused by an exclusive lock and multi-PC editing
accDescr: While an app has a file open with an exclusive lock the sync app cannot update and sync errors become the normal state; editing the same file on several PCs produces a conflict copy and the one-folder-one-file assumption collapses
lock["The app opens with an exclusive lock"] --> nosync["Cannot sync; sync errors become the normal state"]
multi["The same file is edited on several PCs"] --> conflict["A conflict copy is produced"]
conflict --> dup["A duplicate with a PC name or copy"]
dup --> bad["The one-folder-one-file assumption collapses"]
Figure 13: An exclusive lock makes sync errors the normal state, and editing on several PCs invites misbehavior from a conflict copy.
5.6. Antivirus and the Search Indexer Induce Hydration
It is not only the business app that reads file contents. A full scan by antivirus software, and the search indexer, also induce hydration if they touch the contents of a placeholder. Microsoft Defender and similar products skip files that have the RECALL_ON_DATA_ACCESS attribute at on-demand scan time, but that is a product-side response, and you cannot assume every security product will show the same care. If you see symptoms such as “the network and disk peg every night at scan time” or “files that were supposed to be online-only have all materialized by morning”, suspect this line.14
flowchart TB
accTitle: Hydration induced by a security product or the search indexer
accDescr: When a full scan or the search indexer touches the contents of a placeholder, a product that respects the RECALL attribute skips, but a product that does not hydrates every file and causes nighttime bandwidth pressure or morning materialization
av["A full scan or the search indexer"] --> care{"Respects the RECALL attribute?"}
care -->|A product that respects it| skip["Skips the placeholder"]
care -->|A product that does not| hyd["Touches the contents and hydrates"]
hyd --> sym1["Bandwidth and disk peg at night"]
hyd --> sym2["By morning the files have all materialized"]
Figure 14: A scan that does not respect the attribute induces hydration of every file, and it appears as nighttime load or morning materialization.
6. App-Development Response — Respect Placeholders
The basic policy as a developer is to treat a placeholder not as “a broken file” but as “a file that has a fetch cost”.
- Judge from attributes at enumeration time, and do not open carelessly. In a folder scan, first confirm from attributes (the judgment in Chapter 4) whether it is online-only, and open only files whose contents you need. Give processing that is “not fatal if missing” — log collection, hash computation, preview generation — the option to skip placeholders.
// Define values that FileAttributes in .NET does not define, as numbers
const FileAttributes RecallOnDataAccess = (FileAttributes)0x00400000;
const FileAttributes RecallOnOpen = (FileAttributes)0x00040000;
static bool IsCloudPlaceholder(FileAttributes attributes) =>
(attributes & (RecallOnDataAccess | RecallOnOpen | FileAttributes.Offline)) != 0;
foreach (var file in new DirectoryInfo(watchFolder).EnumerateFiles("*.csv"))
{
if (IsCloudPlaceholder(file.Attributes))
{
log.Warn($"{file.Name} is online-only; skipping this time");
continue;
}
Import(file.FullName);
}
flowchart TB
accTitle: The path of judging from attributes at enumeration time and then opening
accDescr: In a folder scan, first confirm attributes at enumeration; if it is a placeholder, skip and leave a warning log, and run import only on the other files, so that careless hydration is avoided
enum["Confirm attributes at enumeration"] --> ph{"Placeholder?"}
ph -->|Yes| skip["Skip and leave a warning log"]
ph -->|No| imp["Run the import"]
skip -.-> note["The policy of opening only files whose contents you need"]
Figure 15: Judge from attributes at enumeration time and skip a placeholder without opening it, so that careless hydration is avoided.
- Note that FILE_FLAG_OPEN_NO_RECALL is not a guarantee of “do not download”. Specifying this flag on CreateFile can indicate the intent that “data obtained should be left on the remote side and not written back to local storage”. It is, however, a flag only for not making obtained data resident locally; if you read the contents, the data transfer itself still occurs. If you want to avoid the bandwidth and latency themselves, finish with attributes, size, and timestamps alone — do not request read access (open with access rights 0, use metadata from the enumeration result). That is the safest.9
flowchart TB
accTitle: The effect and limits of FILE_FLAG_OPEN_NO_RECALL
accDescr: FILE_FLAG_OPEN_NO_RECALL is a flag for not making obtained data resident locally; if you read the contents the data transfer itself still occurs, so if you want to avoid the transfer the safest is to finish with metadata such as attributes
flag["Open with the NO_RECALL flag"] --> read["Read the contents"]
read --> transfer["A data transfer occurs"]
transfer --> nolocal["It does not become resident locally"]
meta["Finish with metadata alone"] --> safe["No transfer occurs; the safest"]
Figure 16: FILE_FLAG_OPEN_NO_RECALL only keeps it from becoming resident locally; if you want to avoid the transfer itself, finish with metadata alone.
- Put “this is under OneDrive” in the error message. On a read failure, just confirming whether the target path is under
%OneDrive%and including that in the message greatly reduces triage time for the field and the help desk. If you detect a cloud-file-family error such as 0x8007016A, the ideal is to tell the user “please check the state of OneDrive”. - Do not put the app’s data folder under OneDrive. In a KFM environment, “Documents” is also under OneDrive. Put the app’s settings, database, and working files in
%ProgramData%or%LocalAppData%, and do not choose Desktop or Documents as the default save location or the default import folder. How to decide what to put where is summarized in “How to Choose Where a Windows App Stores Local Data”. - Decide the behavior when the user chooses a location under OneDrive. For an app that lets the user choose a save location, include in the spec in advance a design decision such as warning when the chosen path is under OneDrive (under the path of the
OneDrive/OneDriveCommercialenvironment variables), or refusing only the placement of a lock file or a DB.
7. IT-Side Response — Control with Pins and Policy
From the IT position, the realistic operation is not “turn Files On-Demand off entirely” but guaranteeing real content only where the business needs it.
- Pin the folders a business app reads. Choose “Always keep on this device” from Explorer’s right-click menu, or run
attrib +p -u <folder> /s /dfrom an imaging script (you specify-uat the same time so that a mix of already-online-only files is reliably switched to pinned). A pinned file has its real content guaranteed locally and is also outside the automatic conversion to online-only discussed later.72 - Configure KFM and Files On-Demand “on purpose”, not “it was on when we noticed”. The main policies (Group Policy / Intune) are as follows.111
| Purpose | Policy (registry value) | Effect |
|---|---|---|
| Control of Files On-Demand | Use OneDrive Files On-Demand (FilesOnDemandEnabled) | On: new users default to online-only. Off: classic full sync |
| Bulk apply of KFM | Silently move Windows known folders to OneDrive (KFMSilentOptIn) | Move Desktop and similar without a user action |
| Forbid KFM | Prevent users from moving their Windows known folders to OneDrive (KFMBlockOptIn) | Forbid moving known folders |
| Forbid turning KFM off | Prevent users from redirecting their Windows known folders to their PC (KFMBlockOptOut) | Forbid the user turning it off |
| Reduce team-site capacity | Convert synced team site files to online-only (DehydrateSyncedTeamSites) | Make synced team sites online-only (note that it works in the direction of the real content disappearing) |
- Know how Storage Sense moves. Storage Sense has a feature that automatically returns cloud files that have not been opened for a number of days to online-only, and you can configure the number of days with the policy (ConfigStorageSenseCloudContentDehydrationThreshold). The default is 0 (do not return automatically), but if a user has turned it on from the settings screen, or the organization has configured it for low-capacity devices, “a file that opened last week is back to a cloud icon” happens as normal behavior. A pinned file is out of scope, so “pin business folders” works here as well.122
flowchart TB
accTitle: Branches of Storage Sense's automatic conversion to online-only
accDescr: In Storage Sense's automatic free-up, a pinned file is out of scope and the real content is kept; an unpinned file that has not been opened for a number of days is returned to online-only
ss["Storage Sense automatic free-up"] --> pin{"Pinned?"}
pin -->|Yes| stay["Out of scope; the real content is kept"]
pin -->|No| old{"Not opened for a number of days?"}
old -->|Yes| dehyd["Returned to online-only"]
old -->|No| keep["The real content is kept"]
ss -.-> def["Default 0 does not return automatically"]
Figure 17: Storage Sense returns a file that has not been opened for a number of days to online-only, but a pin is out of scope.
- Estimate the impact before you disable Files On-Demand. Disabling FilesOnDemandEnabled becomes classic full-download sync, but disk consumption and the bandwidth load of the first sync jump. Microsoft recommends leaving it on, and you should treat disabling it as a limited measure after confirming that “the target users’ data volume is small” and “there is disk headroom”.112
- Build it into the support procedure. Putting the next chapter’s triage procedure into the inquiry template for “a file on the desktop will not open” keeps the quality of the response even when the person handling it changes.
8. Triage Procedure — When You Are Asked “The File Will Not Open”
When you take the consultation, confirm from the top down.
| # | What to confirm | How | What you learn |
|---|---|---|---|
| 1 | Is the path under OneDrive? | Confirm the sync root with echo %OneDrive% and match it against the target path. Also confirm the real path of “Desktop” in Explorer’s address bar |
Whether KFM / OneDrive is involved |
| 2 | The file’s state | Confirm U (online-only), P (pinned), and O with attrib <path>. Also look at “Size on disk” in properties |
Whether the real content is local, or it is a placeholder |
| 3 | Whether OneDrive is running | The taskbar icon (signed in, paused, error), Get-Process OneDrive |
Whether hydration is possible. 0x8007016A is typically stopped or misconfigured8 |
| 4 | The network | Corporate proxy, bandwidth, reachability to the OneDrive service | Whether the download itself is possible |
| 5 | Free disk space | Free space on the target volume. At low capacity there is also a policy by which OneDrive blocks downloads | Another factor in hydration failure |
| 6 | A record of the failure | Note the app’s error code and the time it occurred, and match them against the sync app’s error display | Whether it is an app-side problem or a OneDrive-side problem |
The stopgap is to right-click the target folder and choose “Always keep on this device” (or attrib +p /s /d). That lines up the real content locally and the business can resume. On top of that, decide whether the essential cause is on the app side (Chapter 6) or the IT side (Chapter 7) as the permanent response.
flowchart TB
accTitle: The path from a stopgap to a permanent response
accDescr: As a stopgap, setting the target folder to Always keep on this device lines up the real content locally so the business can resume; on top of that you decide whether the essential cause is on the app side or the IT side and proceed to a permanent response
aid["Pin as a stopgap"] --> restore["The real content is lined up locally"]
restore --> resume["The business resumes"]
resume --> judge{"Where is the essential cause?"}
judge -->|App side| dev["To the Chapter 6 response"]
judge -->|IT side| ops["To the Chapter 7 response"]
Figure 18: The stopgap is to pin, line up the real content, and resume the business; the permanent response proceeds after deciding whether it is the app side or the IT side.
If you have confirmed this far and “the path is not under OneDrive” and “it is not a placeholder either”, you proceed to other staple causes such as a shared folder or path length. “Pitfalls of Network Drives and UNC Paths” and “MAX_PATH and Windows Path/Filename Pitfalls” are the map for what comes next.
9. Summary
- KFM may have moved the real Desktop, Documents, and Pictures under
C:\Users\<name>\OneDrive\. An app that assumes a fixed path breaks here. Resolving with the known-folder APIs is the first step. - Files On-Demand is on by default, and placeholders with no local content exist as a matter of course. A placeholder is a Cloud Files API (cldflt.sys) reparse point, and opening it hydrates automatically.
- State can be judged from file attributes (OFFLINE / RECALL_ON_DATA_ACCESS / PINNED / UNPINNED) and appears as O, P, and U in attrib. Checking attributes alone does not cause a download.
- Business-app accidents appear as hydration failure when offline, a full download from a batch process, code that does not expect the attributes, interaction between FileSystemWatcher and sync, conflict between an exclusive lock and sync, and hydration induced by a security product.
- On the app side, the basics are “judge from attributes and do not open carelessly”, “do not put the data folder under OneDrive”, and “say that it is under OneDrive when you error”.
- On the IT side, you create the intended state with “pinning business folders” and “policy control of KFM, Files On-Demand, and Storage Sense”.
- Triage can be walked mechanically in the order path → attrib → OneDrive running → network → free space → record.
The next time you are asked “the file is there but it will not open”, ask this first.
Is that file really on the local disk? Or is only the appearance of the cloud sitting there?
Related Articles
- The Depths of Windows I/O (Part 5) — NTFS Internals: Understanding the File System Through the MFT
- A Practical Guide to FileSystemWatcher - Handling Missed and Duplicate Events
- Pitfalls of Network Drives and UNC Paths — Working With File Servers (Shared Folders) From a Business Application
- Mutual Exclusion Fundamentals for File-Based Integration - Best Practices for File Locks and Atomic Claims
- How to Choose Where a Windows App Stores Local Data — A Decision Table for SQLite / JSON / Registry / Access
- MAX_PATH and Windows Path/Filename Pitfalls — the 260-Character Limit, Reserved Names, Trailing Dots, and Case Sensitivity
Related Consulting Areas
KomuraSoft LLC handles investigation of business-app failures that involve OneDrive and cloud storage — “an import that used to work no longer works after a PC replacement”, “a file will not open only on a particular PC” — design and remediation of file processing and watch processing that assume placeholders, and reviews of save-location design in a KFM / Files On-Demand environment. Starting from isolating the symptom is fine — please feel free to get in touch.
- Windows Application Development
- Bug Investigation & Root-Cause Analysis
- Technical Consulting & Design Review
- Contact Us
References
-
Microsoft Learn, Redirect and move Windows known folders to OneDrive. That KFM moves Desktop, Documents, and Pictures under OneDrive, and the prompt, silent-apply, forbid-turn-off, and forbid-move policies. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Recommended sync app configuration. That Files On-Demand is on by default and leaving it on is recommended, and that Storage Sense cleans up “locally available files that are not pinned”. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Support, Save disk space with OneDrive Files On-Demand for Windows. The three Files On-Demand states and the “Always keep on this device” and “Free up space” actions. ↩ ↩2 ↩3
-
Microsoft Learn, Build a Cloud Sync Engine that Supports Placeholder Files. An overview of the Cloud Files API, that a placeholder holds only about 1KB of metadata and opening it hydrates automatically, that the reparse point is hidden from processes other than the sync engine and those under %systemroot%, and the toast and block for background hydration. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, File Attribute Constants. The definitions and values of FILE_ATTRIBUTE_OFFLINE, RECALL_ON_OPEN, RECALL_ON_DATA_ACCESS, PINNED, and UNPINNED. ↩ ↩2
-
Microsoft Learn, attrib. The attrib command syntax and the attribute flags including O (offline), P (pinned), and U (unpinned). ↩ ↩2
-
Microsoft Learn, Query and set Files On-Demand states in Windows. Confirming Files On-Demand state with attrib and setting it with +p, -p, and +u, and the CldFlt service. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Error 0x8007016a when copying files in OneDrive. That error 0x8007016A “The cloud file provider is not running” occurs when OneDrive is misconfigured or stopped, and the resolution steps. ↩ ↩2 ↩3
-
Microsoft Learn, CreateFileW function (fileapi.h). That FILE_FLAG_OPEN_NO_RECALL is a flag indicating that “requested data should be left on the remote side and not transferred back to local storage” (it does not prevent obtaining the data itself), and obtaining attributes by opening with access rights 0. ↩ ↩2
-
Microsoft Learn, Handling placeholders. That a placeholder should have FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS set, and that a careless read or write to a file with this attribute invites unnecessary hydration or data corruption. ↩ ↩2
-
Microsoft Learn, IT Admins - Use OneDrive policies to control sync settings. The policies for configuring the OneDrive sync app with GPO/Intune, including FilesOnDemandEnabled, KFMSilentOptIn, KFMBlockOptIn, KFMBlockOptOut, and DehydrateSyncedTeamSites. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Policy CSP - Storage. That Storage Sense can make cloud files that have not been opened for a number of days online-only, the default 0 (do not return automatically), and configuration of 0–365 days. ↩ ↩2 ↩3
-
Microsoft Support, What do the OneDrive icons mean?. The meaning of the status icons shown in Explorer, such as the cloud and the check marks. ↩
-
Microsoft Learn, Plan for an Azure File Sync deployment. That an antivirus scan can cause recall of a file with the RECALL_ON_DATA_ACCESS attribute, and that Microsoft Defender and similar products skip files with this attribute at on-demand scan time. ↩
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
Investigating Event Logs in Practice with Get-WinEvent — Filtering Speed Decides How Long the Investigation Takes
How to make Windows event log investigation efficient with PowerShell. Covers why filtering with Where-Object is slow, when to use Filter...
Apps That Break on Resume from Sleep — How Windows Power Events Work and How to Build Business Apps That Survive Them
You opened the laptop and the business app's connections were dead — the cause is a design that never accounted for sleep. This article c...
DllMain and the Loader Lock — The Real Reason You're Told to "Do Nothing in DLL Initialization"
Why you must not call LoadLibrary or synchronize with other threads from DllMain. Drawing on primary sources, this article explains how t...
What "Not Responding" Really Is — How Windows Decides an App Has Hung, and How to Design Apps That Don't
Windows' "Not Responding" is a mechanism in which the OS judges that a window has not retrieved a message for 5 seconds and replaces it w...
Spurious Wakeups — Why Condition Variables Wake "Without Being Notified" and How to Wait Correctly on Windows
A condition variable's wait can return even when no notification has arrived (a spurious wakeup). This article explains, from the Windows...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
We support Windows desktop applications that involve resident processing, device integration, operational logging, and maintainable structure.
Frequently Asked Questions
Common questions about the topic of this article.
- A business app says "file not found" and cannot read a CSV I put on the desktop. Why?
- In many cases the desktop folder itself has been moved under C:\Users\<username>\OneDrive\Desktop by OneDrive's Known Folder Move (KFM), or the file has become an online-only placeholder. An app that assumes a fixed path such as C:\Users\<username>\Desktop cannot find the file after the move. Even when the path is correct, an online-only file can fail to open when OneDrive is stopped or the network is unhealthy. First confirm whether the target path is under OneDrive, and check with the attrib command whether U (online-only) is set. As a stopgap, you can secure the real content locally with "Always keep on this device" on the right-click menu.
- Can a program tell whether a file is online-only?
- Yes. An online-only placeholder carries attributes such as FILE_ATTRIBUTE_OFFLINE and FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS (0x00400000), so you can judge the state from the file attributes without downloading the contents. Getting attributes or enumerating a folder does not cause hydration (download). In .NET some values are not defined on FileAttributes, so you cast to an integer and test with bitwise operations. If you truly need to open without reading the contents, a means such as CreateFile's FILE_FLAG_OPEN_NO_RECALL is also available.
- Does turning Files On-Demand off solve the problem?
- Treat turning it off as a last resort. Disabling it downloads every file in the sync scope locally, so disk capacity and the network load of the first sync become large, and Microsoft also recommends leaving it on. In practice it is more flexible to set only the folders a business app reads to "Always keep on this device" (pin them). More fundamentally, the reliable fix is to redesign so that the app's data folder and import folder are not under OneDrive's management.
- I set "Always keep on this device", but some files eventually go back to a cloud icon. Why?
- First confirm with the attrib command that the file really has the pin (P attribute). A pinned file is outside Storage Sense's automatic conversion to online-only, but a file that is only "locally available" because someone opened it, without pinning, can be returned to online-only after a period depending on Storage Sense settings and policy. A user's own "Free up space" action, and a policy that makes team-site files online-only (DehydrateSyncedTeamSites), also return the cloud icon. For folders that must stay local for the business, operate by pinning at folder scope.