diff --git a/system/core/devmgr/devhost/devhost.cpp b/system/core/devmgr/devhost/devhost.cpp
index e61707f7c727fe3146bb3726e19e48236f79aea6..77a8667500ed2f8b8d8dfb44f8e468b6dbeeccab 100644
--- a/system/core/devmgr/devhost/devhost.cpp
+++ b/system/core/devmgr/devhost/devhost.cpp
@@ -584,12 +584,8 @@ static zx_status_t dh_handle_rpc_read(zx_handle_t h, DevcoordinatorConnection* c
     char buffer[512];
     const char* path = mkdevpath(conn->dev, buffer, sizeof(buffer));
 
-    // Double-check that Open (the only message we forward)
+    // TODO(ZX-3073): Double-check that Open (the only message we forward)
     // cannot be mistaken for an internal dev coordinator RPC message
-    static_assert(fuchsia_io_DirectoryOpenOrdinal <
-                  fuchsia_device_manager_ControllerCreateDeviceStubOrdinal ||
-                  fuchsia_io_DirectoryOpenOrdinal >
-                  fuchsia_device_manager_ControllerRemoveDeviceOrdinal);
 
     auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
     if (hdr->ordinal == fuchsia_io_DirectoryOpenOrdinal) {
diff --git a/system/core/devmgr/devhost/rpc-server.cpp b/system/core/devmgr/devhost/rpc-server.cpp
index a24f96297f5d3464f56e3f8c4de094e0452c339b..7164054d79a76036ca9f7c9a9a1ddad4255ec028 100644
--- a/system/core/devmgr/devhost/rpc-server.cpp
+++ b/system/core/devmgr/devhost/rpc-server.cpp
@@ -656,23 +656,25 @@ static const fuchsia_io_Node_ops_t kNodeOps = {
 };
 
 zx_status_t devhost_fidl_handler(fidl_msg_t* msg, fidl_txn_t* txn, void* cookie) {
-    fidl_message_header_t* hdr = (fidl_message_header_t*) msg->bytes;
-    if (hdr->ordinal >= fuchsia_io_NodeCloneOrdinal &&
-        hdr->ordinal <= fuchsia_io_NodeIoctlOrdinal) {
-        return fuchsia_io_Node_dispatch(cookie, txn, msg, &kNodeOps);
-    } else if (hdr->ordinal >= fuchsia_io_FileReadOrdinal &&
-               hdr->ordinal <= fuchsia_io_FileGetVmoOrdinal) {
-        return fuchsia_io_File_dispatch(cookie, txn, msg, &kFileOps);
-    } else if (hdr->ordinal >= fuchsia_io_DirectoryOpenOrdinal &&
-               hdr->ordinal <= fuchsia_io_DirectoryWatchOrdinal) {
-        return fuchsia_io_Directory_dispatch(cookie, txn, msg, &kDirectoryOps);
-    } else if (hdr->ordinal >= fuchsia_io_DirectoryAdminMountOrdinal &&
-               hdr->ordinal <= fuchsia_io_DirectoryAdminGetDevicePathOrdinal) {
-        return fuchsia_io_DirectoryAdmin_dispatch(cookie, txn, msg, &kDirectoryAdminOps);
-    } else {
-        auto conn = static_cast<DevfsConnection*>(cookie);
-        return conn->dev->MessageOp(msg, txn);
+    zx_status_t status = fuchsia_io_Node_try_dispatch(cookie, txn, msg, &kNodeOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
+    }
+    status = fuchsia_io_File_try_dispatch(cookie, txn, msg, &kFileOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
+    }
+    status = fuchsia_io_Directory_try_dispatch(cookie, txn, msg, &kDirectoryOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
     }
+    status = fuchsia_io_DirectoryAdmin_try_dispatch(cookie, txn, msg, &kDirectoryAdminOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
+    }
+
+    auto conn = static_cast<DevfsConnection*>(cookie);
+    return conn->dev->MessageOp(msg, txn);
 }
 
 } // namespace devmgr
diff --git a/system/fidl/fuchsia-io/io.fidl b/system/fidl/fuchsia-io/io.fidl
index 27f143137bec568875614913796ce530525042e5..7b3b5bafe854f3f5b9d9f9658b69b033454d823a 100644
--- a/system/fidl/fuchsia-io/io.fidl
+++ b/system/fidl/fuchsia-io/io.fidl
@@ -85,14 +85,14 @@ const uint32 OPEN_FLAG_STATUS = 0x01000000;
 [Layout="Simple", FragileBase]
 interface Node {
     // Create another connection to the same remote object.
-    0x80000001: Clone(uint32 flags, request<Node> object);
+    Clone(uint32 flags, request<Node> object);
 
     // Terminates connection with object.
-    0x80000002: Close() -> (zx.status s);
+    Close() -> (zx.status s);
 
     // Returns extra information about the type of the object.
     // If the |Describe| operation fails, the connection is closed.
-    0x80000006: Describe() -> (NodeInfo info);
+    Describe() -> (NodeInfo info);
 
     // An event produced eagerly by a fidl server if requested
     // by open flags.
@@ -102,19 +102,19 @@ interface Node {
     // to open, |info| contains descriptive information about
     // the object (the same as would be returned by |Describe|),
     // otherwise it is null.
-    0x80000007: -> OnOpen(zx.status s, NodeInfo? info);
+    -> OnOpen(zx.status s, NodeInfo? info);
 
     // Synchronizes updates to the node to the underlying media, if it exists.
-    0x81000001: Sync() -> (zx.status s);
+    Sync() -> (zx.status s);
 
     // Acquire information about the node.
-    0x81000002: GetAttr() -> (zx.status s, NodeAttributes attributes);
+    GetAttr() -> (zx.status s, NodeAttributes attributes);
 
     // Update information about the node.
-    0x81000003: SetAttr(uint32 flags, NodeAttributes attributes) -> (zx.status s);
+    SetAttr(uint32 flags, NodeAttributes attributes) -> (zx.status s);
 
     // Deprecated. Only for use with compatibility with devhost.
-    0x81000004: Ioctl(uint32 opcode, uint64 max_out, vector<handle>:MAX_IOCTL_HANDLES handles, vector<uint8>:MAX_BUF in)
+    Ioctl(uint32 opcode, uint64 max_out, vector<handle>:MAX_IOCTL_HANDLES handles, vector<uint8>:MAX_BUF in)
         -> (zx.status s, vector<handle>:MAX_IOCTL_HANDLES handles, vector<uint8>:MAX_BUF out);
 };
 
@@ -192,36 +192,36 @@ const uint32 VMO_FLAG_EXACT = 0x00020000;
 interface File : Node {
     // Read 'count' bytes at the seek offset.
     // The seek offset is moved forward by the number of bytes read.
-    0x82000001: Read(uint64 count) -> (zx.status s, vector<uint8>:MAX_BUF data);
+    Read(uint64 count) -> (zx.status s, vector<uint8>:MAX_BUF data);
 
     // Read 'count' bytes at the provided offset.
     // Does not affect the seek offset.
-    0x82000002: ReadAt(uint64 count, uint64 offset) -> (zx.status s, vector<uint8>:MAX_BUF data);
+    ReadAt(uint64 count, uint64 offset) -> (zx.status s, vector<uint8>:MAX_BUF data);
 
     // Write data at the seek offset.
     // The seek offset is moved forward by the number of bytes written.
-    0x82000003: Write(vector<uint8>:MAX_BUF data) -> (zx.status s, uint64 actual);
+    Write(vector<uint8>:MAX_BUF data) -> (zx.status s, uint64 actual);
 
     // Write data to the provided offset.
     // Does not affect the seek offset.
-    0x82000004: WriteAt(vector<uint8>:MAX_BUF data, uint64 offset) -> (zx.status s, uint64 actual);
+    WriteAt(vector<uint8>:MAX_BUF data, uint64 offset) -> (zx.status s, uint64 actual);
 
-    0x82000005: Seek(int64 offset, SeekOrigin start) -> (zx.status s, uint64 offset);
+    Seek(int64 offset, SeekOrigin start) -> (zx.status s, uint64 offset);
 
     // Shrink the file size to 'length' bytes.
-    0x82000006: Truncate(uint64 length) -> (zx.status s);
+    Truncate(uint64 length) -> (zx.status s);
 
     // Acquire the Directory::Open rights and flags used to access this file.
-    0x82000007: GetFlags() -> (zx.status s, uint32 flags);
+    GetFlags() -> (zx.status s, uint32 flags);
 
     // Change the Directory::Open flags used to access the file.
     // Supported flags which can be turned on / off:
     // - OPEN_FLAG_APPEND
-    0x82000008: SetFlags(uint32 flags) -> (zx.status s);
+    SetFlags(uint32 flags) -> (zx.status s);
 
     // Acquire a VMO representing this file, if there is one, with the
     // requested access rights.
-    0x82000009: GetVmo(uint32 flags) -> (zx.status s, handle<vmo>? vmo);
+    GetVmo(uint32 flags) -> (zx.status s, handle<vmo>? vmo);
 };
 
 // Dirent type information associated with the results of ReadDirents.
@@ -275,17 +275,17 @@ struct WatchedEvent {
 [Layout = "Simple"]
 interface DirectoryWatcher {
     // TODO(smklein): Convert this to a vector of WatchedEvents, when possible.
-    0x84000001: OnEvent(vector<uint8>:MAX_BUF events);
+    OnEvent(vector<uint8>:MAX_BUF events);
 };
 
 // Directory defines a node which is capable of containing other Objects.
 [Layout = "Simple", FragileBase]
 interface Directory : Node {
     // Open a new object relative to this directory object.
-    0x83000001: Open(uint32 flags, uint32 mode, string:MAX_PATH path, request<Node> object);
+    Open(uint32 flags, uint32 mode, string:MAX_PATH path, request<Node> object);
 
     // Remove an object relative to this directory object.
-    0x83000002: Unlink(string:MAX_PATH path) -> (zx.status s);
+    Unlink(string:MAX_PATH path) -> (zx.status s);
 
     // Reads a collection of variably sized dirents into a buffer.
     // The number of dirents in a directory may be very large: akin to
@@ -304,22 +304,22 @@ interface Directory : Node {
     //   // Unterminated name of entry.
     //   char name[0];
     // }
-    0x83000003: ReadDirents(uint64 max_bytes) -> (zx.status s, vector<uint8>:MAX_BUF dirents);
+    ReadDirents(uint64 max_bytes) -> (zx.status s, vector<uint8>:MAX_BUF dirents);
 
     // Reset the directory seek offset.
-    0x83000004: Rewind() -> (zx.status s);
+    Rewind() -> (zx.status s);
 
     // Acquire a token to a Directory which can be used to identify
     // access to it at a later point in time.
-    0x83000005: GetToken() -> (zx.status s, handle? token);
+    GetToken() -> (zx.status s, handle? token);
 
     // Within the directory, rename an object named src to the name dst, in
     // a directory represented by token.
-    0x83000006: Rename(string:MAX_PATH src, handle dst_parent_token, string:MAX_PATH dst) -> (zx.status s);
+    Rename(string:MAX_PATH src, handle dst_parent_token, string:MAX_PATH dst) -> (zx.status s);
 
     // Within the directory, create a link to an object named src by the name
     // dst, within a directory represented by token.
-    0x83000007: Link(string:MAX_PATH src, handle dst_parent_token, string:MAX_PATH dst) -> (zx.status s);
+    Link(string:MAX_PATH src, handle dst_parent_token, string:MAX_PATH dst) -> (zx.status s);
 
     // Watches a directory, receiving events of added messages on the
     // watcher request channel.
@@ -336,7 +336,7 @@ interface Directory : Node {
     //
     // Mask specifies a bitmask of events to observe.
     // Options must be zero; it is reserved.
-    0x83000008: Watch(uint32 mask, uint32 options, handle<channel> watcher) -> (zx.status s);
+    Watch(uint32 mask, uint32 options, handle<channel> watcher) -> (zx.status s);
 };
 
 const uint32 MOUNT_CREATE_FLAG_REPLACE = 0x00000001;
@@ -379,23 +379,23 @@ interface DirectoryAdmin : Directory {
     // All future requests to this node will be forwarded to the remote filesytem.
     // To re-open a node without forwarding to the remote target, the node
     // should be opened with OPEN_FLAG_NO_RMOTE.
-    0x85000001: Mount(Directory remote) -> (zx.status s);
+    Mount(Directory remote) -> (zx.status s);
 
     // Atomically create a directory with a provided path, and mount the
     // remote handle to the newly created directory.
-    0x85000002: MountAndCreate(Directory remote, string:MAX_FILENAME name, uint32 flags) -> (zx.status s);
+    MountAndCreate(Directory remote, string:MAX_FILENAME name, uint32 flags) -> (zx.status s);
 
     // Unmount this filesystem. After this function returns successfully,
     // all connections to the filesystem will be terminated.
-    0x85000003: Unmount() -> (zx.status s);
+    Unmount() -> (zx.status s);
 
     // Detach a node which was previously attached to this directory
     // with Mount.
-    0x85000004: UnmountNode() -> (zx.status s, Directory? remote);
+    UnmountNode() -> (zx.status s, Directory? remote);
 
     // Query the filesystem for filesystem-specific information.
-    0x85000005: QueryFilesystem() -> (zx.status s, FilesystemInfo? info);
+    QueryFilesystem() -> (zx.status s, FilesystemInfo? info);
 
     // Acquire the path to the device backing this filesystem, if there is one.
-    0x85000006: GetDevicePath() -> (zx.status s, string:MAX_PATH? path);
+    GetDevicePath() -> (zx.status s, string:MAX_PATH? path);
 };
diff --git a/system/fidl/fuchsia-minfs/minfs.fidl b/system/fidl/fuchsia-minfs/minfs.fidl
index bd23a1b3943050e186c0cc196a4327ad02ca4e06..dd4458ffbe9c02f2930449932312e2fe25abadb2 100644
--- a/system/fidl/fuchsia-minfs/minfs.fidl
+++ b/system/fidl/fuchsia-minfs/minfs.fidl
@@ -59,8 +59,8 @@ struct Metrics {
 [Layout="Simple"]
 interface Minfs {
     // Acquires metrics about the currently running filesystem.
-    0x8A000001: GetMetrics() -> (zx.status status, Metrics? metrics);
+    GetMetrics() -> (zx.status status, Metrics? metrics);
 
     // Toggle the metrics collection system on or off.
-    0x8A000002: ToggleMetrics(bool enable) -> (zx.status status);
+    ToggleMetrics(bool enable) -> (zx.status status);
 };
diff --git a/system/ulib/fs/connection.cpp b/system/ulib/fs/connection.cpp
index 589f716f34844ade50fb48e8eda7db6eed406a00..567298d55072db8b65d846d5d64834f9ad28202f 100644
--- a/system/ulib/fs/connection.cpp
+++ b/system/ulib/fs/connection.cpp
@@ -843,22 +843,23 @@ zx_status_t Connection::HandleFsSpecificMessage(fidl_msg_t* msg, fidl_txn_t* txn
 }
 
 zx_status_t Connection::HandleMessage(fidl_msg_t* msg, fidl_txn_t* txn) {
-    fidl_message_header_t* hdr = reinterpret_cast<fidl_message_header_t*>(msg->bytes);
-    if (hdr->ordinal >= fuchsia_io_NodeCloneOrdinal &&
-        hdr->ordinal <= fuchsia_io_NodeIoctlOrdinal) {
-        return fuchsia_io_Node_dispatch(this, txn, msg, &kNodeOps);
-    } else if (hdr->ordinal >= fuchsia_io_FileReadOrdinal &&
-               hdr->ordinal <= fuchsia_io_FileGetVmoOrdinal) {
-        return fuchsia_io_File_dispatch(this, txn, msg, &kFileOps);
-    } else if (hdr->ordinal >= fuchsia_io_DirectoryOpenOrdinal &&
-               hdr->ordinal <= fuchsia_io_DirectoryWatchOrdinal) {
-        return fuchsia_io_Directory_dispatch(this, txn, msg, &kDirectoryOps);
-    } else if (hdr->ordinal >= fuchsia_io_DirectoryAdminMountOrdinal &&
-               hdr->ordinal <= fuchsia_io_DirectoryAdminGetDevicePathOrdinal) {
-        return fuchsia_io_DirectoryAdmin_dispatch(this, txn, msg, &kDirectoryAdminOps);
-    } else {
-        return HandleFsSpecificMessage(msg, txn);
+    zx_status_t status = fuchsia_io_Node_try_dispatch(this, txn, msg, &kNodeOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
+    }
+    status = fuchsia_io_File_try_dispatch(this, txn, msg, &kFileOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
+    }
+    status = fuchsia_io_Directory_try_dispatch(this, txn, msg, &kDirectoryOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
+    }
+    status = fuchsia_io_DirectoryAdmin_try_dispatch(this, txn, msg, &kDirectoryAdminOps);
+    if (status != ZX_ERR_NOT_SUPPORTED) {
+        return status;
     }
+    return HandleFsSpecificMessage(msg, txn);
 }
 
 } // namespace fs
diff --git a/system/ulib/minfs/vnode.cpp b/system/ulib/minfs/vnode.cpp
index 9d9e27ce6979447dd20f14f81de8316d04531f74..ad4b9e619ac383d5c82801db5bd061ab88bc1e6a 100644
--- a/system/ulib/minfs/vnode.cpp
+++ b/system/ulib/minfs/vnode.cpp
@@ -104,13 +104,7 @@ private:
     }
 
     zx_status_t HandleFsSpecificMessage(fidl_msg_t* msg, fidl_txn_t* txn) final {
-        fidl_message_header_t* hdr = reinterpret_cast<fidl_message_header_t*>(msg->bytes);
-        if (hdr->ordinal >= fuchsia_minfs_MinfsGetMetricsOrdinal &&
-            hdr->ordinal <= fuchsia_minfs_MinfsToggleMetricsOrdinal) {
-            return fuchsia_minfs_Minfs_dispatch(this, txn, msg, Ops());
-        }
-        zx_handle_close_many(msg->handles, msg->num_handles);
-        return ZX_ERR_NOT_SUPPORTED;
+        return fuchsia_minfs_Minfs_dispatch(this, txn, msg, Ops());
     }
 };