| 583 | } |
| 584 | |
| 585 | Status ValidateNodeDef(const NodeDef& node_def, const OpDef& op_def) { |
| 586 | if (node_def.op() != op_def.name()) { |
| 587 | return errors::InvalidArgument( |
| 588 | "NodeDef op '", node_def.op(), "' does not match ", |
| 589 | SummarizeOpDef(op_def), "; NodeDef: ", FormatNodeDefForError(node_def)); |
| 590 | } |
| 591 | |
| 592 | bool seen_control = false; |
| 593 | size_t num_inputs = 0; |
| 594 | // TODO(josh11b): Unify the input field validation. |
| 595 | for (const string& input : node_def.input()) { |
| 596 | if (absl::StartsWith(input, "^")) { |
| 597 | seen_control = true; |
| 598 | if (input.find(':') != string::npos) { |
| 599 | return errors::InvalidArgument("Control input '", input, |
| 600 | "' must not have ':' in NodeDef: ", |
| 601 | FormatNodeDefForError(node_def)); |
| 602 | } |
| 603 | } else if (seen_control) { |
| 604 | return errors::InvalidArgument("Non-control input '", input, |
| 605 | "' after control input in NodeDef: ", |
| 606 | FormatNodeDefForError(node_def)); |
| 607 | } else { |
| 608 | ++num_inputs; |
| 609 | } |
| 610 | } |
| 611 | |
| 612 | std::unordered_map<string, const OpDef::AttrDef*> op_attrs; |
| 613 | for (const auto& attr : op_def.attr()) { |
| 614 | if (!gtl::InsertIfNotPresent(&op_attrs, attr.name(), &attr)) { |
| 615 | return errors::InvalidArgument("OpDef has duplicate attr name '", |
| 616 | attr.name(), |
| 617 | "': ", SummarizeOpDef(op_def)); |
| 618 | } |
| 619 | } |
| 620 | for (const auto& attr : node_def.attr()) { |
| 621 | // Allow internal optional attributes with names starting with "_". |
| 622 | if (absl::StartsWith(attr.first, "_")) { |
| 623 | continue; |
| 624 | } |
| 625 | auto iter = op_attrs.find(attr.first); |
| 626 | if (iter == op_attrs.end()) { |
| 627 | // A common cause of this error is that TensorFlow has made a |
| 628 | // backwards-compatible change to the NodeDef (e.g., adding a |
| 629 | // new attr with a default value), but the binary consuming the |
| 630 | // NodeDef does not know about the new attribute; the solution |
| 631 | // in these cases is to ensure that the binary consuming the |
| 632 | // NodeDef is built with a version of TensorFlow no earlier than |
| 633 | // the binary producing it. |
| 634 | return errors::InvalidArgument( |
| 635 | "NodeDef mentions attr '", attr.first, "' not in ", |
| 636 | SummarizeOpDef(op_def), |
| 637 | "; NodeDef: ", FormatNodeDefForError(node_def), |
| 638 | ". (Check whether your GraphDef-interpreting binary is up to date " |
| 639 | "with your GraphDef-generating binary.)."); |
| 640 | } |
| 641 | // If attr value is placeholder, do not check it. |
| 642 | if (attr.second.placeholder().empty()) { |